Skip to content
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

Trait impl from where clause (ParamEnv) takes precedence over freestanding trait impl #84218

Closed
krtab opened this issue Apr 15, 2021 · 5 comments
Labels
A-traits Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@krtab
Copy link
Contributor

krtab commented Apr 15, 2021

Hi!

Sorry for the poor title, I have no better idea. Feel free to change it to something more appropriate.

I tried this code:

pub fn take_n_bits<S, L>(x: u64, start_from_right: S, length: L) -> u64
where
    u64: std::ops::Shr<S, Output = u64>,
    L: Into<usize>
{
    let shifted : u64 = x >> start_from_right;
    let mask : u64 = !0 >> (std::mem::size_of::<u64>() * 8 - length.into());
    shifted & mask
}

which I expect to compile fine. But instead, I get the typing error:

error[E0308]: mismatched types
 --> src/lib.rs:7:28
  |
1 | pub fn take_n_bits<S, L>(x: u64, start_from_right: S, length: L) -> u64
  |                    - this type parameter
...
7 |     let mask : u64 = !0 >> (std::mem::size_of::<u64>() * 8 - length.into());
  |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found `usize`
  |
  = note: expected type parameter `S`
                       found type `usize`

error: aborting due to previous error

(playground link)

Meta

(afaict this is present in stable, beta and nightly)

rustc --version --verbose:

rustc 1.53.0-nightly (d0695c908 2021-04-12)
binary: rustc
commit-hash: d0695c9081b16077d0aed368bccaf437d77ff497
commit-date: 2021-04-12
host: x86_64-unknown-linux-gnu
release: 1.53.0-nightly
LLVM version: 12.0.0
@krtab krtab added the C-bug Category: This is a bug. label Apr 15, 2021
@Globidev
Copy link

here is a minimal reproduction of the issue

use std::ops::Shr;

fn works() { 1_u64 >> 2_u32; }

fn breaks<T>()
where 
    u64: Shr<T>
{ 
    1_u64 >> 2_u32; 
}

It looks like the compiler unnecessarily restricts to the Shr<T> impl instead of inferring the type parameter of Shr from the rhs and picking Shr<u32> in that case

More strange scenarios (as of Nightly version: 1.53.0-nightly (2021-04-14 16bf626a31cb5b121d0b)):

use std::ops::Shr;

fn works() { 1_u64 >> 2_u32; }

fn breaks<T>()          where u64: Shr<T>              { 1_u64 >> 2_u32; }
fn breaks_too<T>()      where u64: Shr<u32> + Shr<T>   { 1_u64 >> 2_u32; }
fn breaks_as_well<T>()  where u64: Shr<u32> + Shr<T>   { Shr::<_>::shr(1_u64, 2_u32); } // Should be infered to `Shr::<u32>` from my understanding, but doesn't seem to be the case
fn works_though<T>()    where u64: Shr<T>              { Shr::<u32>::shr(1_u64, 2_u32); }
fn works_too<T>()       where u64: Shr<u32> + Shr<T>   { Shr::<u32>::shr(1_u64, 2_u32); }

fn works_more_surprisingly<T, U>()
where 
    u64: Shr<T> + Shr<U> // An additional bound on another generic parameter seems to fix the resolution ??
{ 
    1_u64 >> 2_u32; 
}

fn works_more_surprisingly_in_full_form_too<T, U>()
where 
    u64: Shr<T> + Shr<U>
{ 
    Shr::<_>::shr(1_u64, 2_u32);
}

playground link for those

@jonas-schievink
Copy link
Contributor

I think this is currently working as expected, since trait bounds on where clauses have precedence over freestanding trait implementations

@Globidev
Copy link

I feel like that does not explain the last two cases of the last snippet above though, where having two trait bounds instead of one suddenly "re-enables" the freestanding trait implementation

@Cerber-Ursi
Copy link
Contributor

Probably duplicate of #24066.

@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@fmease fmease added A-traits Area: Trait system A-inference Area: Type inference T-types Relevant to the types team, which will review and decide on the PR/issue. and removed needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. labels Jan 23, 2024
@fmease fmease changed the title Trait inference issue Trait impl from where clause (ParamEnv / caller bounds) takes precedence over freestanding trait impl Jan 23, 2024
@fmease fmease removed the A-inference Area: Type inference label Jan 23, 2024
@fmease
Copy link
Member

fmease commented Jan 23, 2024

Closing as duplicate of #24066.

@fmease fmease closed this as not planned Won't fix, can't repro, duplicate, stale Jan 23, 2024
@fmease fmease changed the title Trait impl from where clause (ParamEnv / caller bounds) takes precedence over freestanding trait impl Trait impl from where clause (ParamEnv) takes precedence over freestanding trait impl Jan 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-traits Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants