Вот над чем я работаю (детская площадка):
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
?
Это ограничение длины массива; он не может использовать какие-либо параметры или общие границы, даже если они являются областью действия. Проблема возникла во время стабилизации связанных констант, и было принято решение стабилизировать их без нее.
Это ограничение специфично для параметров длины массива, все остальное работает:
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;
}
Проблему можно отследить здесь и здесь
Эта ошибка отслеживается здесь: github.com/rust-lang/rust/issues/60551