Skip to content

Wrong infered type when an additional constrain added #64681

Closed as duplicate

Description

@kurnevsky

In the function f I have to specify bool explicitly while f differs from g in constrains only:

use rand::Rng;
use rand::distributions::{Distribution, Standard};

fn f<S, R>(rng: &mut R) -> bool
where
    R: Rng,
    Standard: Distribution<S>,
{
    rng.gen::<bool>()
}

fn g<R>(rng: &mut R) -> bool
where
    R: Rng
{
    rng.gen()
}

Playground

Not sure if it's an actual bug but it looks like the type inference should work the same way in both cases.

Activity

  1. added
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Sep 22, 2019
  2. cuviper commented on Sep 23, 2019

    @cuviper
    Member

    For posterity, here's the error where it inferred S instead of bool:

    error[E0308]: mismatched types
     --> src/lib.rs:9:5
      |
    4 | fn f<S, R>(rng: &mut R) -> bool
      |                            ---- expected `bool` because of return type
    ...
    9 |     rng.gen()
      |     ^^^^^^^^^ expected bool, found type parameter
      |
      = note: expected type `bool`
                 found type `S`
      = help: type parameters must be constrained to match other types
      = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    

    If f's constraint is changed to Standard: Distribution<bool>, it infers bool just fine.

    I also tried Distribution<S> + Distribution<bool> and vice versa, but either way infers S.

  3. orangeturtle739 commented on Jan 5, 2020

    @orangeturtle739

    Edit: minimized the example even more:
    Here's another example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=bcd9a0d9507ac1e42ec7b0ce9f7a5f42

    pub struct Foo {
        pub x: i32,
    }
    
    impl From<i32> for Foo {
        fn from(x: i32) -> Foo {
            Foo {x}
        }
    }
    
    pub fn add_1_foo<T>(y: T) -> Foo
    where
        Foo: From<T>,
    {
        let foo = Foo::from(y);
        let foo_1 = Foo::from(1);
        Foo {
            x: foo.x + foo_1.x
        }
    }
    
    pub fn add_1_foo_works(y: i32) -> Foo
    {
        let foo = Foo::from(y);
        let foo_1 = Foo::from(1);
        Foo {
            x: foo.x + foo_1.x
        }
    }

    Results in (on 1.42.0-nightly (2019-12-29 da3629b05f8f1b425a73)):

    error[E0308]: mismatched types
      --> src/lib.rs:16:27
       |
    11 | pub fn add_1_foo<T>(y: T) -> Foo
       |                  - this type parameter
    ...
    16 |     let foo_1 = Foo::from(1);
       |                           ^ expected type parameter `T`, found integer
       |
       = note: expected type parameter `T`
                            found type `{integer}`
       = help: type parameters must be constrained to match other types
       = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    

    It seems like since the Foo: From<T> constraint is there, it expects all uses of Foo::from to be on a T. But T has to be equal to i32, and it still doesn't work. Also, I can't figure out any way to make add_1_foo compile just by adding type annotations. Changing the Foo::from(1) line to let foo_1 : Foo = 1.into(); works, but that just avoids calling from.

  4. installgentoo commented on Jan 17, 2020

    @installgentoo

    Just encountered this exact bug.

  5. lcnr commented on Aug 1, 2025

    @lcnr
    Contributor

    Closing as duplicate of #24066

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceA-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions