rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.34k stars 12.72k forks source link

Trait implementation changes cross-crate with `const_generics` and `const_evaluatable_checked` #82957

Open AuroransSolis opened 3 years ago

AuroransSolis commented 3 years ago

edit: updated for generic_const_exprs

Issue two of three I'm going to be filing tonight with very similar code regarding const_generics and const_evaluatable_checked.

This is the code that causes the bug:

#![feature(generic_const_exprs, array_map)]

pub struct ConstCheck<const CHECK: bool>;

pub trait True {}
impl True for ConstCheck<true> {}

pub trait OrdesDec {
    type Newlen;
    type Output;

    fn pop(self) -> (Self::Newlen, Self::Output);
}

impl<T, const N: usize> OrdesDec for [T; N]
where
    ConstCheck<{N > 1}>: True,
    [T; N - 1]: Sized,
{
    type Newlen = [T; N - 1];
    type Output = T;

    fn pop(self) -> (Self::Newlen, Self::Output) {
        let mut iter = IntoIter::new(self);
        let end = iter.next_back().unwrap();
        let new = [(); N - 1].map(move |()| iter.next().unwrap());
        (new, end)
    }
}

The issue occurs when called from another crate like so:

use ordes::OrdesDec;

fn main() {
    let foo = [0, 1, 2, 3, 4];
    let (foo, pop) = foo.pop();
}

Now you're probably thinking to yourself, "Hey Auro, isn't that exactly the same code as in #82956?" Nope, not quite. The foo assignment is just 0, not 0u8. When called in the above manner, the following error message is produced:

error[E0599]: the method `pop` exists for array `[{integer}; 5]`, but its trait bounds were not satisfied
 --> src/main.rs:5:26
  |
5 |     let (foo, pop) = foo.pop();
  |                          ^^^ method cannot be called on `[{integer}; 5]` due to unsatisfied trait bounds
  |
 ::: /media/ellen-nyan/DnData/Workspace/Repos/playground-3/blah/src/lib.rs:3:1
  |
3 | pub struct ConstCheck<const CHECK: bool>;
  | ----------------------------------------- doesn't satisfy `ConstCheck<{_: bool}>: True`
  |
  = note: the following trait bounds were not satisfied:
          `ConstCheck<{_: bool}>: True`
          which is required by `[{integer}; 5]: OrdesDec`

When called internally (like in a test module), the test runs without issue (see here for a few tests that all run perfectly fine under cargo test).

Meta

rustc --version --verbose:

rustc 1.52.0-nightly (35dbef235 2021-03-02)
binary: rustc
commit-hash: 35dbef235048f9a2939dc20effe083ca483c37ff
commit-date: 2021-03-02
host: x86_64-unknown-linux-gnu
release: 1.52.0-nightly
LLVM version: 11.0.1
lcnr commented 2 years ago

so the issue seems to be caused by the caller not having feature(generic_const_exprs) enabled.

while the error is a bit surprising, it doesn't really seem worth it to spend a lot of effort on fixing this issue.