Страницы

Поиск по вопросам

суббота, 9 марта 2019 г.

Реализация внешнего trait для внешнего шаблона, параметризованного локальным типом в Rust

После перехода с январьской версии компилятора Rust на beta. Обнаружил что код подобный этому не компилируется http://is.gd/oX7GWN
use std::fmt::{Display, Formatter, Error};
struct MyLocalType;
type MyResult = Result;
impl Display for MyResult { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { f.write_str("some test string") } }
fn main() { let r: MyResult = Ok(MyLocalType); println!("{}" , r); }
Это ошибка компилятора, или теперь внешние параметризованные типы нужно всегда "заворачивать" в свои ?


Ответ

Ответ, скопированый с англоязычного stackoverflow:
https://stackoverflow.com/questions/29789877/can-not-implement-trait-from-another-crate-for-generic-type-from-another-crate-p There's no direct way to solve this for a pure alias like type. The code is the same as
impl Display for Result and the compiler can't ensure that there will be no conflicting implementations in other crates (aka, can't ensure that the implementation is 'coherent'). Being able to do it is definitely useful sometimes, but it was unfortunately a bug that the compiler accepted it before. Solutions include: defining a proper wrapper type for Result, e.g. struct MyResult(Result); defining your own enum: enum MyResult { Ok(MyType), Err(String) } define a wrapper type, but only use it when printing, i.e. write println!("{}", Wrapper(r)); instead of println!("{}", r); Both of these make MyResult a local type, and so the impl then should be legal.
Описание на русском, как его понял я:
Теперь нет способа реализовывать типаж для стороннего обобщённого типа, пусть даже и параметризованного локальным типом. Так как компилятор не может быть уверен, что реализация будет согласована со всеми другими реализациями.
Чтобы решить эту проблему нужно сделать тип полностью локальным. Eсть несколько способов:
«Обернуть» его в локальный тип-обёртку, например: struct MyResult(Result); Объявить свой собственный Result-подобный тип: enum MyResult { Ok(MyType), Err(String) } Или же обернуть его, но использовать обёртку только там, где необходим требуемый типаж, например: println!("{}", Wrapper(r)); вместо println!("{}", r);

Комментариев нет:

Отправить комментарий