Constant patterns with private fields can match irrefutably, which is a semver hazard
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
// crate foo
#[derive(PartialEq)]
pub struct Foo { not_pub: () }
pub const FOO: Foo = Foo { not_pub: () };
// crate bar
use foo:::*;
fn test(foo: Foo) {
match foo {
FOO => (),
}
}
I expected to see this happen: Crate bar should fail to compile; the match against foo should not be considered exhaustive. Foo has private fields, so crate foo should be free to change its internals such that FOO is no longer the only possible value of the type.
Instead, this happened: Crate bar compiles, which restricts foo's freedom to change what should be private implementation details.
Meta
rustc --version --verbose:
rustc 1.98.0 (88d9e12ae 2026-08-18)
binary: rustc
commit-hash: 88d9e12ae178fab0fb5cc050a94da85685d449ea
commit-date: 2026-08-18
host: x86_64-unknown-linux-gnu
release: 1.98.0
LLVM version: 22.1.8
@rustbot label T-lang A-patterns A-exhaustiveness-checking A-crate-compat A-visibility
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the two-crate Rust example and inspect the compiler's pattern exhaustiveness checking for constant patterns, private fields, and cross-crate visibility. A regression test should demonstrate that matching FOO from crate bar is rejected as non-exhaustive, preserving crate foo's freedom to change private representation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100