rust-lang / rust

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

Generic bounds don't seem to be used in consteval #50308

Closed glandium closed 5 years ago

glandium commented 6 years ago

The following code fails to compile

struct Bar<T> (
    std::marker::PhantomData<(T, [(); 0 - !(std::mem::align_of::<T>() > 3) as usize])>,
);

The error is:

error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
 --> src/main.rs:2:45
  |
2 |     std::marker::PhantomData<(T, [(); 0 - !(std::mem::align_of::<T>() > 3) as usize])>,
  |                                             ^^^^^^^^^^^^^^^^^^^^^^^ `T` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `T`
  = help: consider adding a `where T: std::marker::Sized` bound
  = note: required by `std::mem::align_of`

which makes no sense since there is an implicit T: Sized bound from the struct definition. Even with an explicit bound, the error occurs.

Combined with associated consts, this leads to weird error messages:

trait Foo: Sized {
    const align: usize = std::mem::align_of::<Self>();
}

struct Bar<T: Foo> (
    std::marker::PhantomData<(T, [(); 0 - !(T::align > 3) as usize])>,
);
error[E0599]: no function or associated item named `align` found for type `T` in the current scope
 --> src/main.rs:6:45
  |
6 |     std::marker::PhantomData<(T, [(); 0 - !(T::align > 3) as usize])>,
  |                                             ^^^^^^^^ function or associated item not found in `T`
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `align`, perhaps you need to implement it:
          candidate #1: `Foo`
brunoczim commented 6 years ago

Another example:

use std::marker::PhantomData;

pub trait AsIndex: Copy {

    const MAX: usize;

    fn cast_to(self) -> usize;

    fn cast_from(idx: usize) -> Self;

}

impl AsIndex for usize {

    const MAX: usize = !0usize >> 1;

    fn cast_to(self) -> usize {self}

    fn cast_from(idx: usize) -> usize {idx}

}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct BiMap<L, R>
where
    L: AsIndex,
    R: AsIndex,
{
    left: [Option<usize>; <L as AsIndex>::MAX + 1],
    right: [Option<usize>; <R as AsIndex>::MAX + 1],
    _marker: PhantomData<(L, R)>,
}

Results in:

error[E0277]: the trait bound `L: AsIndex` is not satisfied
  --> src/main.rs:29:27
   |
29 |     left: [Option<usize>; <L as AsIndex>::MAX + 1],
   |                           ^^^^^^^^^^^^^^^^^^^ the trait `AsIndex` is not implemented for `L`
   |
   = help: consider adding a `where L: AsIndex` bound
note: required by `AsIndex::MAX`
  --> src/main.rs:5:5
   |
5  |     const MAX: usize;
   |     ^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `R: AsIndex` is not satisfied
  --> src/main.rs:30:28
   |
30 |     right: [Option<usize>; <R as AsIndex>::MAX + 1],
   |                            ^^^^^^^^^^^^^^^^^^^ the trait `AsIndex` is not implemented for `R`
   |
   = help: consider adding a `where R: AsIndex` bound
note: required by `AsIndex::MAX`
  --> src/main.rs:5:5
   |
5  |     const MAX: usize;
   |     ^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
pythonesque commented 6 years ago

I was running into this as well. See also https://github.com/rust-lang/rust/issues/50439 -- it may not be the same issue, but it's also using this array indexing trick.

oli-obk commented 5 years ago

This is a symptom of https://github.com/rust-lang/rust/issues/43408