Skip to content

Inconsistent rustc inference #141103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mathisbot opened this issue May 16, 2025 · 4 comments
Closed

Inconsistent rustc inference #141103

mathisbot opened this issue May 16, 2025 · 4 comments
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.

Comments

@mathisbot
Copy link
Contributor

I tried this code:

use std::marker::PhantomData;

struct DefaultU;

struct MockType<T, U = DefaultU> {
    data: T,
    _phantom: PhantomData<U>,
}

impl<T, U> MockType<T, U> {
    fn new(value: T) -> Self {
        Self {
            data: value,
            _phantom: PhantomData,
        }
    }
}

fn main() {
    // Compiles
    MockType::<()>::new(());

    // Does not compile
    MockType::new(());
}

See on Compiler Explorer.

In main, I try to create a MockType and the compiler is acting inconsistently.
As I am not adding any information by specifiying ::<()>, I would expect it to either be able to infer that T = () in the second case or unable to default to DefaultU in the first.

Meta

rustc --version --verbose:

rustc 1.89.0-nightly (d97326eab 2025-05-15)
binary: rustc
commit-hash: d97326eabfc3b2c33abcb08d6bc117aefa697cb7
commit-date: 2025-05-15
host: x86_64-pc-windows-gnu
release: 1.89.0-nightly
LLVM version: 20.1.4

but it also happens on stable (1.87.0)

Backtrace

error[E0282]: type annotations needed
  --> <source>:24:5
   |
24 |     MockType::new(());
   |     ^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the struct `MockType`
   |
help: consider specifying the generic arguments
   |
24 |     MockType::<(), U>::new(());
   |             +++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
Compiler returned: 1

@mathisbot mathisbot added the C-bug Category: This is a bug. label May 16, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 16, 2025
@theemathas
Copy link
Contributor

This is working as intended. Default generics only apply if generics are specified but the defaulted generic is omitted. To get the desired behavior, you can write MovkType::<_>::new(()).

@mathisbot
Copy link
Contributor Author

This is working as intended. Default generics only apply if generics are specified but the defaulted generic is omitted. To get the desired behavior, you can write MovkType::<_>::new(()).

That's what I was trying to show, I feel the behavior is inconsistent.
I'm not adding any information by writing ::<_>, and I don't see what reason there could be to block rustc from using DefaultU.
Not adding ::<_> or adding it with a type other than () prevents compilation anyway, so what's to stop rustc from adding it itself? It would make the code more readable (especially when it's not () but a more complex type).

Maybe I'm just missing something.

@theemathas
Copy link
Contributor

theemathas commented May 17, 2025

In my understanding, what you're requesting is actually rather complicated, and people haven't yet figured out how to do this. (Since rust has to figure out whether you want the types to be inferred vs defaulted.) See #27336

@mathisbot
Copy link
Contributor Author

That makes sense, I suspected there was a subtlety (otherwise the problem would have been solved by now, I guess).

For completeness, here's what the linked Issue says:

fn foo<T = u64>(t: T) { ... }

fn main() { foo::<_>(22) }
//                ^
//                |
//    What type gets inferred here?

The question at hand is what type gets inferred for the type parameter T. On the one hand, the user specified a default of u64. On the other, integer literals typically fallback to i32.

@mathisbot mathisbot closed this as not planned Won't fix, can't repro, duplicate, stale May 17, 2025
@jieyouxu jieyouxu added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.
Projects
None yet
Development

No branches or pull requests

4 participants