Константа, связанная с трейтом, недоступна в контексте определения трейта, несмотря на соответствующую привязку трейта

Вот над чем я работаю (детская площадка):

pub trait DisplayWidth {
    const DISPLAY_WIDTH: usize;

    fn chunks<'a>(s: &'a str) -> Chunks<'a, Self> {
        Chunks(s.chars(), PhantomData)
    }
}

pub struct Chunks<'a, T: ?Sized>(std::str::Chars<'a>, PhantomData<T>);

impl<'a, T: DisplayWidth> Iterator for Chunks<'a, T> {
    // 4 bytes in a max-width char
    type Item = SmallString<[u8; 4 * T::DISPLAY_WIDTH]>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut s = SmallString::new();
        for _ in 0..T::DISPLAY_WIDTH {
            s.push(self.0.next()?);
        }
        Some(s)
    }
}

Это генерирует E0599, но только для определения type Item:

error[E0599]: no associated item named `DISPLAY_WIDTH` found for type parameter `T` in the current scope
  --> src/geometry/tile.rs:23:41
   |
23 |     type Item = SmallString<[u8; 4 * T::DISPLAY_WIDTH]>;
   |                                         ^^^^^^^^^^^^^ associated item not found in `T`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait

Интересен тот факт, что rustc вообще не жалуется на использование ассоциированной константы в цикле for; только в связанном определении типа.

Я подозреваю, что это ошибка компилятора: учитывая, что T ограничен DisplayWidth, он должен быть доступен в контексте определения типа, связанного с трейтом, но его просто нет. Тем не менее, я спрашиваю здесь, прежде чем подавать отчет об ошибке в rustc, потому что я не уверен в этом на 100%.

Обходной путь, который я использую на данный момент, прост: определите отдельную константу и используйте ее:

pub const CHUNK_WIDTH: usize = 4;
    type Item = SmallString<[u8; 4 * CHUNK_WIDTH]>;

Однако есть ли решение, которое позволило бы использовать DisplayWidth::DISPLAY_WIDTH?

Эта ошибка отслеживается здесь: github.com/rust-lang/rust/issues/60551

Ibraheem Ahmed 11.12.2020 15:48
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
3
1
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это ограничение длины массива; он не может использовать какие-либо параметры или общие границы, даже если они являются областью действия. Проблема возникла во время стабилизации связанных констант, и было принято решение стабилизировать их без нее.

Это ограничение специфично для параметров длины массива, все остальное работает:

pub trait Shape {
    const SIDES: usize;
}

pub trait SimpleIter {
    const Item: usize;    
}

impl<T: Shape> SimpleIter for T {
    // this is fine
    const Item: usize = T::SIDES;
}

Проблему можно отследить здесь и здесь

Другие вопросы по теме