Skip to content

Add a new lint UNCONSTRUCTABLE_PUB_STRUCT to detect unconstructable public structs#146440

Draft
mu001999 wants to merge 5 commits into
rust-lang:mainfrom
mu001999-contrib:lint/unconstructible_pub_struct
Draft

Add a new lint UNCONSTRUCTABLE_PUB_STRUCT to detect unconstructable public structs#146440
mu001999 wants to merge 5 commits into
rust-lang:mainfrom
mu001999-contrib:lint/unconstructible_pub_struct

Conversation

@mu001999
Copy link
Copy Markdown
Member

@mu001999 mu001999 commented Sep 11, 2025

View all comments

Add a new lint UNCONSTRUCTABLE_PUB_STRUCT to detect unconstructable public structs, based on the following observations:

  1. A public struct with private field(s) cannot be directly constructed from external crates.
  2. Associated functions with a receiver require an already constructed value of type Self.
  3. Therefore, public structs with private fields and their associated functions that take a receiver can be included in the local crate's dead code analysis.
  4. If a public struct with private fields cannot be constructed in any reachable code path, it could be considered dead.

And, the lint UNCONSTRUCTABLE_PUB_STRUCT won't affect the dead-code lint's result, but allow or deny dead-code lint may affect the result of UNCONSTRUCTABLE_PUB_STRUCT

@rustbot rustbot added 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. labels Sep 11, 2025
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Sep 11, 2025

r? @davidtwco

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

@mu001999 mu001999 changed the title Implement lint unconstructible_pub_struct Add a new lint UNCONSTRUCTIBLE_PUB_STRUCT to detect unconstructible public structs Sep 11, 2025
@juntyr
Copy link
Copy Markdown
Contributor

juntyr commented Sep 11, 2025

Would the lint fire on token structs that are public, have private fields, have no public constructor method, but expose a limited number of pre-constructed objects, e.g. through a static that contains an optional token?

@mu001999
Copy link
Copy Markdown
Member Author

a static that contains an optional token

won't fire like private types used in such places

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 480b1d7 to 021712b Compare September 15, 2025 07:39
@davidtwco
Copy link
Copy Markdown
Member

Nominating for t-lang to decide whether we want this lint, then I'll review the implementation.

Also, s/unconstructible/unconstructable.

@davidtwco davidtwco added the I-lang-nominated Nominated for discussion during a lang team meeting. label Sep 17, 2025
@mu001999 mu001999 changed the title Add a new lint UNCONSTRUCTIBLE_PUB_STRUCT to detect unconstructible public structs Add a new lint UNCONSTRUCTABLE_PUB_STRUCT to detect unconstructable public structs Sep 17, 2025
@traviscross traviscross added the P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. label Sep 17, 2025
@bors

This comment was marked as resolved.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 6075d81 to 497ad71 Compare October 18, 2025 09:57
@rustbot

This comment has been minimized.

@bors

This comment was marked as resolved.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 497ad71 to b3b3a05 Compare October 19, 2025 05:22
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Oct 19, 2025

This PR was rebased onto a different master 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.

@Darksonn
Copy link
Copy Markdown
Member

Does this trigger on structs that are intended only as marker types in generic parameters?

@mu001999
Copy link
Copy Markdown
Member Author

mu001999 commented Oct 24, 2025

Does this trigger on structs that are intended only as marker types in generic parameters?

Such types usually have intended private unit fields and this won't trigger on them. This will only trigger types with trivial fields but not be used or cannot be constructed.

@nikomatsakis
Copy link
Copy Markdown
Contributor

Are there examples of code in the wild that is affected by this lint?

@scottmcm
Copy link
Copy Markdown
Member

scottmcm commented Nov 5, 2025

I worry about completeness here. If I have something like pub struct Foo(pub [u8]); it's not "constructible" in a sense, but it might be entirely expected anyway. What if there's something only created via slice_from_raw_parts and pointer casts to get &MyType?


Musing: what if this was signature-based, say? Could it be phrased as "why is this pub when it's not in a signature; maybe it should be pub(crate)?" or something?

@joshtriplett
Copy link
Copy Markdown
Member

We discussed this in today's @rust-lang/lang meeting.

Was there any particular motivating use case that led to proposing this? Can you point to some code that motivated this?

We wondered about potential corner cases, notably structs that are only constructed in unsafe code. For instance, something using repr(C) or repr(transparent) that's constructed via transmute, or a dynamically sized type that requires unsafe code to construct. We're hoping those can be handled and won't produce false positives.

Once those are addressed, we'd like to see the (triaged) results of a crater run with this lint marked as deny-by-default, so we can get an idea of 1) how widespread this is and 2) whether this catches any issues.

@traviscross traviscross added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Nominated for discussion during a lang team meeting. labels Nov 5, 2025
@traviscross
Copy link
Copy Markdown
Contributor

Please renominate for lang when these answers are available.

@mu001999 mu001999 marked this pull request as draft November 6, 2025 03:18
@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 Nov 6, 2025
@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from b3b3a05 to a1aaeb6 Compare November 12, 2025 01:42
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from c6455d2 to 1ed009a Compare May 17, 2026 03:20
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 1ed009a to 60e74c5 Compare May 17, 2026 04:14
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 60e74c5 to f494476 Compare May 17, 2026 05:36
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from f494476 to 01730b2 Compare May 17, 2026 06:32
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 01730b2 to 3209e4a Compare May 17, 2026 07:55
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 3209e4a to 9aa49af Compare May 17, 2026 09:09
@rust-log-analyzer

This comment has been minimized.

@mu001999 mu001999 force-pushed the lint/unconstructible_pub_struct branch from 9aa49af to 7625326 Compare May 17, 2026 10:49
@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs A-rustdoc-js Area: Rustdoc's JS front-end labels May 17, 2026
@mu001999
Copy link
Copy Markdown
Member Author

@bors try

@rust-bors

This comment has been minimized.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 17, 2026

💥 Test timed out after 21600s

@mu001999
Copy link
Copy Markdown
Member Author

@bors try

@rust-bors

This comment has been minimized.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 18, 2026

☔ The latest upstream changes (presumably #156670) made this pull request unmergeable. Please resolve the merge conflicts.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 18, 2026

☀️ Try build successful (CI)
Build commit: 0611f7d (0611f7de057c584b8771102fde7aed6c70c71d3b, parent: 507271bc119683008ec719ecee48814e8ac86c65)

@mu001999
Copy link
Copy Markdown
Member Author

@craterbot check

@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-146440 created and queued.
🤖 Automatically detected try build 0611f7d
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

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

Labels

A-run-make Area: port run-make Makefiles to rmake.rs A-rustdoc-js Area: Rustdoc's JS front-end A-rustdoc-search Area: Rustdoc's search feature I-lang-radar Items that are on lang's radar and will need eventual work or consideration. P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. perf-regression Performance regression. S-waiting-on-crater Status: Waiting on a crater run to be completed. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output.

Projects

None yet

Development

Successfully merging this pull request may close these issues.