You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While switching an API from returning Box<Trait> to returning impl Trait (it was using Box only to isolate the class implementing the trait), I noticed an incompatibility. The user of the API is now required to import the trait in order to call method defined by the trait, which slightly reduces the ergonomy of the API.
Take this code, which compiles fine:
mod x {use std::io::Write;structOpaque;implWriteforOpaque{fnwrite(&mutself, _:&[u8]) -> ::std::io::Result<usize>{Ok(1)}fnflush(&mutself) -> ::std::io::Result<()>{Ok(())}}pubfnget_writer() -> Box<Write>{Box::new(Opaque)}}fnmain(){letmut writer = x::get_writer();
writer.write_all(b"foo").unwrap();}
Now, if we just change the return type from Box<Write> to impl<Write>, like this:
mod x {use std::io::Write;structOpaque;implWriteforOpaque{fnwrite(&mutself, _:&[u8]) -> ::std::io::Result<usize>{Ok(1)}fnflush(&mutself) -> ::std::io::Result<()>{Ok(())}}pubfnget_writer() -> implWrite{Opaque}}fnmain(){letmut writer = x::get_writer();
writer.write_all(b"foo").unwrap();}
it no longer compiles:
rustc -O test2.rs
error[E0599]: no method named `write_all` found for type `impl std::io::Write` in the current scope
--> test2.rs:22:12
|
22 | writer.write_all(b"foo").unwrap();
| ^^^^^^^^^
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
1 | use std::io::Write;
|
error: aborting due to previous error
While I can understand the problem, and know how to fix it on the caller side (just use std::io::Write), I am curious why the import was not required when returning a Box. Of course, switching the return is a backward incompatible change anyway (it would break code that explicitly typed writer as Box<Write>), but for simple usages it would be much nicer if the user could just call the method without explicitly importing the trait, as was possible previously.
So in this case switching from boxed return to impl return has slightly reduced the ergonomy of the API. Is there a way to prevent that?
The text was updated successfully, but these errors were encountered:
While switching an API from returning
Box<Trait>
to returningimpl Trait
(it was usingBox
only to isolate the class implementing the trait), I noticed an incompatibility. The user of the API is now required to import the trait in order to call method defined by the trait, which slightly reduces the ergonomy of the API.Take this code, which compiles fine:
Now, if we just change the return type from
Box<Write>
toimpl<Write>
, like this:it no longer compiles:
While I can understand the problem, and know how to fix it on the caller side (just
use std::io::Write
), I am curious why the import was not required when returning aBox
. Of course, switching the return is a backward incompatible change anyway (it would break code that explicitly typedwriter
asBox<Write>
), but for simple usages it would be much nicer if the user could just call the method without explicitly importing the trait, as was possible previously.So in this case switching from boxed return to
impl
return has slightly reduced the ergonomy of the API. Is there a way to prevent that?The text was updated successfully, but these errors were encountered: