Skip to content

lint ineffective #[unstable] annotations on re-exports - #161178

Open
amirHdev wants to merge 8 commits into
rust-lang:mainfrom
amirHdev:unstable-reexport
Open

lint ineffective #[unstable] annotations on re-exports#161178
amirHdev wants to merge 8 commits into
rust-lang:mainfrom
amirHdev:unstable-reexport

Conversation

@amirHdev

@amirHdev amirHdev commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

@rustbot rustbot added 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. labels Aug 16, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@amirHdev
amirHdev marked this pull request as ready for review August 17, 2026 16:53
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 17, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 17, 2026
@rustbot

rustbot commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

r? @mejrs

rustbot has assigned @mejrs.
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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 75 candidates
  • Random selection from 16 candidates

@amirHdev

Copy link
Copy Markdown
Contributor Author

r? clarfonthey

@rustbot rustbot assigned clarfonthey and unassigned mejrs Aug 17, 2026
Comment thread compiler/rustc_passes/src/stability.rs Outdated
};

let (has_target, all_targets_stable) = self.classify_reexport_targets(
[path.res.type_ns, path.res.value_ns, path.res.macro_ns].into_iter().flatten(),

@mejrs mejrs Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
[path.res.type_ns, path.res.value_ns, path.res.macro_ns].into_iter().flatten(),
path.res.present_items()

View changes since the review

Comment thread compiler/rustc_passes/src/stability.rs Outdated
for (span, reexport) in &self.unstable_reexports {
if reexport.has_target && reexport.all_targets_stable {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,

@mejrs mejrs Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you make a standalone lint for this, not reuse UNUSED_ATTRIBUTES? And make it deny by default?

It looks like this fix is just a temporary measure, but a proper fix looks hard so I suspect this will end up becoming somewhat permanent.

View changes since the review

Comment thread compiler/rustc_passes/src/stability.rs Outdated
Comment on lines +589 to +590
// Do not emit the lint if resolution is incomplete or the
// target cannot be classified.

@mejrs mejrs Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can "resolution being incomplete" even happen? And what does "the target cannot be classified" mean?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I switched this to explicit Res handling

Comment thread compiler/rustc_passes/src/stability.rs Outdated
let mut all_targets_stable = true;

for res in targets {
let Some(def_id) = res.opt_def_id() else {

@mejrs mejrs Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this handles re-exports of primitives correctly. We do have modules that re-export primitives, like std::primitive.

View changes since the review

Comment thread compiler/rustc_passes/src/stability.rs Outdated
Comment on lines +572 to +578
fn unstable_reexport_span(&self, item: &'tcx hir::Item<'tcx>) -> Option<Span> {
let attrs = self.tcx.hir_attrs(item.hir_id());
let (stability, span) =
find_attr!(attrs, Stability { stability, span } => (*stability, *span))?;

matches!(stability.level, StabilityLevel::Unstable { .. }).then_some(span)
}

@mejrs mejrs Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this span would be more helpful if it pointed to the item being re-exported

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the attribute span is only kept as the grouping key for grouped reexport for now

@amirHdev
amirHdev requested a review from mejrs August 18, 2026 14:34
@rust-log-analyzer

This comment has been minimized.

@mejrs mejrs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I still need to understand the logic of stability gating better (both what you've added and what's already there), so I'm not done yet

View changes since this review

Comment on lines +2795 to +2823
declare_lint! {
/// The `ineffective_unstable_reexport` lint detects `#[unstable]` attributes
/// on re-exports where the attribute does not make the re-exported path unstable.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![feature(staged_api)]
/// #![stable(feature = "test", since = "1.0.0")]
///
/// #[stable(feature = "test", since = "1.0.0")]
/// pub struct S;
///
/// #[unstable(feature = "reexport", issue = "none")]
/// pub use crate::S as T;
///
/// fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Stability attributes on re-exports do not currently change the
/// stability of an otherwise stable re-exported item.
pub INEFFECTIVE_UNSTABLE_REEXPORT,
Deny,
"detects ineffective `#[unstable]` attributes on re-exports"
}

@mejrs mejrs Aug 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you also feature gate this lint behind the staged_api feature? and add a feature gate test for it?

(If you can suppress the "use #![feature(staged_api)] .." suggestion that'd be nice - we suppress that suggestion elsewhere as well.)

Comment thread library/alloc/src/io/mod.rs Outdated
slice_write_vectored, take,
};

pub use self::buf_read::BufRead;

@petrochenkov petrochenkov Aug 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think having publicly reachable items without any stability annotations is a right thing.
The current stability logic is right in at least one thing - it requires stability annotations on everything reachable.
The new behavior should be the same, IMO, it just needs to make sure that the reexport's stability annotation is compatible with the stability that is actually used (stability of that reexport's ultimate definition).
cc #146028 (comment)

View changes since the review

@amirHdev amirHdev Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree we should keep explicit stability annotations on public re-exports but one concern remains if i am correct. if the intended semantics allow a stable item to be reexported through an unstable path should this lint really reject that case? perhaps the check should only reject reexports that weaken the stability of the ultimate definition

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If cases like this are rare, they can use allow(ineffective_unstable_reexport) with a comment.

@petrochenkov

Copy link
Copy Markdown
Contributor

(Also the lint doesn't follow the lint naming conventions - https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints.)

@amirHdev
amirHdev requested review from mejrs and petrochenkov August 20, 2026 10:47
@rust-bors

This comment has been minimized.

Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 27, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the O-windows Operating system: Windows label Aug 27, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
@rustbot rustbot added O-wasi Operating system: Wasi, Webassembly System Interface O-wasm Target: WASM (WebAssembly), http://webassembly.org/ labels Aug 28, 2026
@rust-log-analyzer

This comment has been minimized.

Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
Comment thread compiler/rustc_lint_defs/src/builtin.rs Outdated

#[derive(Diagnostic)]
#[diag("stability annotation on this re-export does not match the re-exported item")]
pub(crate) struct IncompatibleReexportStability;

@clarfonthey clarfonthey Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be nice to provide the spans of the two attributes being checked, but it does appear that these spans aren't retained in the Stability type you seem to be comparing against. So, perhaps as a compromise, simply stating what the two stability attributes were (even debug-printing them) might be helpful in the output.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, gonna say that debug-printing is fine for now. Since this is just an internal lint, I think it should be fine to just show raw debug output on an initial version.

One small concern is that storing the format string directly might affect perf, but will run perf before merging anyway.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sounds good thanks. it works for me and we can revisit the representation if the perf run shows anything concerning

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like it's fine

Signed-off-by: Amirhossein Akhlaghpour <m9.akhlaghpoor@gmail.com>
@clarfonthey

Copy link
Copy Markdown
Contributor

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 29, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 29, 2026
lint ineffective #[unstable] annotations on re-exports
@clarfonthey

Copy link
Copy Markdown
Contributor

Side note: will code review the whole thing, but will probably pass off to compiler for a final review after verifying the functionality is good for libs, since I'm not familiar enough with the lint code to be able to say it's doing things "the right way" in that sense.

@rust-bors

rust-bors Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: f3482bf (f3482bfb4828183bd9977b4799330b8c188fc5b6)
Base parent: 6bb812b (6bb812b714cce8e08864b7b569303f25ab08eaad)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (f3482bf): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.2% [0.1%, 0.2%] 5
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.5% [-0.5%, -0.5%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary -4.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.2% [-5.2%, -3.2%] 2
All ❌✅ (primary) - - 0

Cycles

Results (secondary 5.6%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
13.8% [8.3%, 17.4%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.6% [-2.7%, -2.5%] 3
All ❌✅ (primary) - - 0

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 475.357s -> 474.541s (-0.17%)
Artifact size: 402.87 MiB -> 402.80 MiB (-0.02%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-macos Operating system: macOS O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-wasm Target: WASM (WebAssembly), http://webassembly.org/ O-windows Operating system: Windows S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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.

7 participants