Type inference can pick private-inaccessible types
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
//! `dep`
pub trait Trait<CrateLocalParam> {
#[doc(hidden)]
fn __do_not_impl_manually();
}
pub fn assert_impls_trait_locally<T, CrateLocalParam>()
where
T: Trait<CrateLocalParam>,
{}
#[macro_export]
macro_rules! crate_local_impl_Trait {( for $T:ty ) => (
const _: () = {
pub(crate) enum CurrentCrate {}
impl $crate::Trait<CurrentCrate> for $T {
fn __do_not_impl_manually() {}
}
};
)}
crate_local_impl_Trait!(for u8); // A
fn _demo() {
assert_impls_trait_locally::<u8, _>(); // OK
}
alongside some ::dep-dependent:
use ::dep::*;
crate_local_impl_Trait!(for u8); // B
fn _demo2() {
// Error, **multiple** impls found !???
assert_impls_trait_locally::<u8, _>(); // ☹️
}
I expected to see this happen: In the context of _demo2, only its crate-local CurrentCrate is in scope. Thus, no inference ambiguity error should ensue.
Instead, this happened:
-
Not only does a type inference ambiguity error occur,
error[E0283]: type annotations needed --> src/lib.rs:21:9 | 21 | assert_impls_some_trait_locally::<u8, _>(); // ☹️ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `CrateLocalParam` declared on the function `assert_impls_some_trait_locally` | note: multiple `impl`s satisfying `u8: Trait<_>` found --> src/lib.rs:17:5 | 17 | crate_local_impl_Trait!(for u8); // B | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: and another `impl` found in the `dep` crate: `impl Trait<dep::_::CurrentCrate> for u8;` note: required by a bound in `dep::assert_impls_some_trait_locally` --> dep/src/lib.rs:10:12 | 8 | pub fn assert_impls_some_trait_locally<T, CrateLocalParam>() | ------------------------------- required by a bound in this function 9 | where 10 | T: Trait<CrateLocalParam>, | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impls_some_trait_locally` = note: this error originates in the macro `crate_local_impl_Trait` (in Nightly builds, run with -Z macro-backtrace for more info) -
but if we remove our own local
crate_local_impl_Trait!(for u8); // Binvocation, type inference will actively try to pick::dep::CurrentCrateforCurrentCrate(rather than saying that no types could be found), resulting in a type privacy error.error: type `dep::_::CurrentCrate` is private --> src/lib.rs:21:9 | 21 | assert_impls_some_trait_locally::<u8, _>(); // ☹️ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type
Meta
Checked on stable and nightly:
rustc --version --verbose:
1.94.0-nightly (2026-01-13 2850ca8295bc253186b2)
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 both Rust examples from the issue with rustc: the case with local and dependency impls, and the case with only the dependency impl. Trace type inference and privacy handling around the generic _ parameter. Done means inaccessible dependency types are not selected and the local invocation does not produce an inference ambiguity.
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
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100