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

Type can no longer be inferred in 1.49 #81317

Open
Skgland opened this issue Jan 24, 2021 · 12 comments
Open

Type can no longer be inferred in 1.49 #81317

Skgland opened this issue Jan 24, 2021 · 12 comments
Assignees
Labels
A-inference Area: Type inference P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@Skgland
Copy link
Contributor

Skgland commented Jan 24, 2021

Code

I tried this code: Johni0702/rtp on the dtls-srtp Branch

I expected to see this happen: Compiles successfully as in 1.48

Instead, this happened: Error E0282 in src/rfc3711.rs

error[E0282]: type annotations needed
   --> src/rfc3711.rs:477:19
    |
476 |         let iv = iv ^ (BigUint::from(1_u8) << (context.session_encr_key.len() * 8));
    |             -- consider giving `iv` a type
477 |         let iv = &iv.to_bytes_be()[1..context.session_encr_key.len() + 1];
    |                   ^^ cannot infer type
    |
    = note: type must be known at this point

error[E0282]: type annotations needed
   --> src/rfc3711.rs:511:19
    |
510 |         let iv = iv ^ (BigUint::from(1_u8) << (context.session_encr_key.len() * 8));
    |             -- consider giving `iv` a type
511 |         let iv = &iv.to_bytes_be()[1..context.session_encr_key.len() + 1];
    |                   ^^ cannot infer type
    |
    = note: type must be known at this point

error: aborting due to 2 previous errors

Version it worked on

It most recently worked on: 1.48

Version with regression

rustc --version --verbose:

rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.49.0

I tried to minimize the code necessary for reproduction and I got it down to:

//file: src/lib.rs
use num::BigUint; // Cargo.toml: num = "0.1"

pub trait Protocol {
    type PacketIndex: Into<u64> + Into<BigUint>;
}

fn from_nothing<T>() -> T {
    todo!()
}

pub fn decrypt_portion<P: Protocol>(index: P::PacketIndex) {
    let iv: BigUint = from_nothing();
    let len: usize = from_nothing();
    let iv = iv ^ (index.into() << 16);
    let iv = iv ^ (BigUint::from(1_u8) << (len * 8));
    let _iv: &[u8] = &iv.to_bytes_be()[1..len + 1];
}
@rustbot rustbot added regression-from-stable-to-stable Performance or correctness regression from one stable version to another. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 24, 2021
@Skgland
Copy link
Contributor Author

Skgland commented Jan 24, 2021

Based on that it worked on stable 1.48 and now doesn't on 1.49 I assume this is a stable to stable regression.

@rustbot modify labels: +regression-from-stable-to-stable-regression-untriaged

@camelid camelid added the A-inference Area: Type inference label Jan 24, 2021
@camelid
Copy link
Member

camelid commented Jan 24, 2021

Minimized further:

use num::BigUint; // Cargo.toml: num = "0.1"

pub trait Protocol: Sized + Default {
    type PacketIndex: Into<u64> + Into<BigUint>;
}

pub fn decrypt_portion<P: Protocol>(index: P::PacketIndex) {
    let iv: BigUint = loop{};
    let len: usize = loop{};
    let iv = iv ^ (index.into() << 16);
    let iv = iv ^ (BigUint::from(1_u8) << (len * 8));
    let _iv: &[u8] = &iv.to_bytes_be()[1..len + 1];
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
warning: unreachable statement
 --> src/lib.rs:9:5
  |
8 |     let iv: BigUint = todo!();
  |                       ------- any code following this expression is unreachable
9 |     let len: usize = todo!();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
  |
  = note: `#[warn(unreachable_code)]` on by default

error[E0282]: type annotations needed
  --> src/lib.rs:12:23
   |
11 |     let iv = iv ^ (BigUint::from(1_u8) << (len * 8));
   |         -- consider giving `iv` a type
12 |     let _iv: &[u8] = &iv.to_bytes_be()[1..len + 1];
   |                       ^^ cannot infer type
   |
   = note: type must be known at this point

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0282`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

@Skgland
Copy link
Contributor Author

Skgland commented Jan 24, 2021

Reduced the code to not use external BigUint type:

use std::ops::{BitXor, Shl};

pub trait Protocol {
    type PacketIndex: Into<u64> + Into<BigUint>;
}

fn from_nothing<T>() -> T {
    todo!()
}

pub fn decrypt_portion<P: Protocol>(index: P::PacketIndex) {
    let iv: BigUint = from_nothing();
    let len: usize = from_nothing();
    let iv = iv ^ (index.into() << 16);
    let iv = iv ^ (BigUint::from(1_u8) << (len * 8));
    let _iv: &[u8] = &iv.to_bytes_be()[1..len + 1];
}

pub struct BigUint;

impl BigUint {
    fn to_bytes_be(&self) -> Vec<u8> {
        todo!()
    }
}

impl From<u8> for BigUint {
    fn from(_: u8) -> Self {
        unimplemented!()
    }
}

impl Shl<usize> for BigUint {
    type Output = BigUint;

    fn shl(self, _rhs: usize) -> Self::Output {
        unimplemented!()
    }
}

impl BitXor for BigUint {
    type Output = BigUint;

    fn bitxor(self, _rhs: Self) -> Self::Output {
        unimplemented!()
    }
}

impl<'a> BitXor<&'a BigUint> for BigUint {
    type Output = BigUint;

    fn bitxor(self, _rhs: &'a BigUint) -> Self::Output {
        unimplemented!()
    }
}

@ojeda
Copy link
Contributor

ojeda commented Jan 24, 2021

pub struct S;

pub trait P {
    type I: Into<u64> + Into<S>;
}

trait A<B> {
    fn m(self, _: B) -> S;
}

impl A<S> for S {
    fn m(self, _: S) -> S {
        todo!()
    }
}

impl A<&'static S> for S {
    fn m(self, _: &'static S) -> S {
        todo!()
    }
}

pub fn f<T: P>(i: T::I) {
    S.m(i.into());
}

@Skgland
Copy link
Contributor Author

Skgland commented Jan 24, 2021

Could this be related to #80816?

@Skgland
Copy link
Contributor Author

Skgland commented Jan 24, 2021

searched nightlies: from nightly-2020-10-01 to nightly-2020-11-14
regressed nightly: nightly-2020-10-07
searched commits: from a1dfd24 to 98edd1f
regressed commit: 08e2d46 (#73905)

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --preserve --start=2020-10-01 --end=2020-11-14 -- check 

Using code:

pub struct S;

pub trait P {
    type I: Into<u64> + Into<S>;
}

trait A<B> {
    fn m(self, _: B) -> S;
}

impl A<S> for S {
    fn m(self, _: S) -> S {
        todo!()
    }
}

impl A<&'static S> for S {
    fn m(self, _: &'static S) -> S {
        todo!()
    }
}

pub fn f<T: P>(i: T::I) {
    let _ = S.m(i.into());
}

@mbartlett21
Copy link
Contributor

An alternate reduction:

use core::ops::Shl;

struct A;

impl A {
    fn a(&self) {}
}

impl Shl<i8> for A {
    type Output = A;
    
    fn shl(self, _: i8) -> A {
        self
    }
}

impl Shl<i32> for A {
    type Output = A;
    
    fn shl(self, _: i32) -> A {
        self
    }
}

pub fn decrypt_portion_no_worky() {
    let iv = A << 16;
    iv.a();
}

pub fn decrypt_portion_works() {
    let iv = A << 16;
    // Calling no methods works?!
}

@Skgland
Copy link
Contributor Author

Skgland commented Jan 25, 2021

@mbartlett21 that does not appear to be a valid reduction as it does not work on 1.48 for me

@Skgland
Copy link
Contributor Author

Skgland commented Jan 25, 2021

use std::ops::BitXor;

pub struct S;

pub trait P {
    type I: Into<u64> + Into<S>;
}

pub fn decrypt_portion<T: P>(index: T::I) {
    let iv = S ^ index.into();
    &iv.to_bytes_be();
}

impl S {
    fn to_bytes_be(&self) -> &[u8] {
        unimplemented!()
    }
}

impl BitXor for S {
    type Output = S;

    fn bitxor(self, _rhs: Self) -> Self::Output {
        unimplemented!()
    }
}

impl<'a> BitXor<&'a S> for S {
    type Output = S;

    fn bitxor(self, _rhs: &'a S) -> Self::Output {
        unimplemented!()
    }
}

this reduction works for me and without changing the error message as with ojedas reduction

@apiraino apiraino added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 27, 2021
@apiraino
Copy link
Contributor

Assigning P-high as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@jackh726 jackh726 added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804 labels Jan 28, 2022
@oli-obk oli-obk self-assigned this Jul 15, 2022
@oli-obk oli-obk added T-types Relevant to the types team, which will review and decide on the PR/issue. and removed WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804 labels Jul 15, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Jul 15, 2022

duplicate of #80816 but keeping open so I make sure to test both repros

@pnkfelix
Copy link
Member

Visiting for P-high review.

After some investigation, I do not think this is quite a duplicate of #80816. Or at least, the examples in #80816 are all now spitting out errors about mulitiple applicable impls. No such message is being emitted here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. 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

9 participants