Is there a way to downcast from Box<dyn Any> initiated with something that impl Write to &dyn Write ? I don't know the concrete type, I just have a field of Box<dyn Any> smth like Rust Playground
The idea is I want to use it differently based on type, if it's just Write in a function I'll just call write but if it's Seek also I want to call seek too.
You can't get a &dyn Write without the compiler generating a dyn Write vtable from the concrete impl Write for TheConcreteType, and there’s no way for the compiler to know that it needs to do that when the Box<dyn Any> is constructed, nor is there any place in dyn Any to store a dyn Write vtable.
What your code is trying to do is, in part, asking the question “does this implement Write”, which is not possible to do in any way whatsoever in generic code. (Read about “specialization” in Rust to learn why not.)
What you can do is define your own trait, which can incorporate Any if you wish:
Problem is I don't know what types will I receive, all I know is it can be Write or Write + Seek.
Can I do somehow blanket Implementation for MyAny for all Write and Write + Seek and then call as_* on that?
Tried like this Rust Playground but getting error[E0119]: conflicting implementations of trait MyAny`
In this case I have a wrapper struct that wraps a Read or a Read + Seek. In the latter case when I'm using the wrapper I can see the seek method too.
Similarly I want to model a Writer wrapper over Write or Write + Seek and in the latter case I want to expose seek too but the actual write method will be different as in the case it's Seek too I first need to read and decrypt the block and only after that write to it, like here rencfs/src/crypto/write.rs at 51fe35679876aa7aa3b20fe53018cc45262d17d3 · radumarias/rencfs · GitHub
So I somehow need to know if I'm Seek also so then I can call read and seek methods as needed.
No, you can’t, because there will be a lot of types where both implementations are applicable and the compiler has no way to choose between them. Ultimately, whoever is giving you these types will need to explicitly choose which behavior they want one way or another.
The best you can do right now is to aim for an API that makes that explicit choice as painless as possible.
To me, that sounds like a completely different operation that shouldn’t share the same name. What should happen if you have a write-only seekable object? Or a read-write object that currently contains junk that should be blindly overwritten instead of encrypted data?
No matter what, when you coerce the value into dyn, you must know statically whether that particular type implements the combination(s) of traits you care about. You cannot make a decision based on "whether this type implements Seek"; you can only require it to implement Seek, or follow a different code path with a different coercion that does not.
In other words, another representation you could use is:
and when you convert to this type, you must already know which enum variant you want to pick — not pick it based on whether Read and Seek are implemented.
But, like @2e71828 said, it seems a lot like you're not just trying to support different things depending on which traits are implemented, but to perform a different operation depending on which traits are implemented. That's not just impossible — it's also bad design. Don't use whether a trait is implemented to decide what a value means.