Hello everyone!
I have a situation/code where i am not being able to define types such that trait method could be called without annotations. Clean code without comments in playground.
Have been wrestling with this for hours, but can not find the syntax/structures of how to describe this properly. I think i understand the problem, why explicit annotations are required. The code without comments is short, but i want to describe a problem context a little bit.
fn main() {
let buf = Buffer {};
let grant: () = buf.grant();
// ^----------This is where the problem starts, returned grant
// has lost it's providers type. If this is fixed, i
// think annotations would not be necessary.
let s = "X".to_string();
s.do_something(&grant);
// ^---- This does not work, but i want to be able to use this short and
// nice syntax.
<String as DoWork<Buffer>>::do_something(&s, &grant);
// ^---- This does what is intended, except that i would like to avoid
// using this long syntax.
}
// =============================
// First part:
// =============================
// The goal for this is to define a trait that allows to influence the structure
// that produced the Grant. Let's say a Vec provides a Grant to mutably modify
// it's contents. Generally it's like wraping `&mut self.vec[..]` and then
// allowing to pass this grant to some other function calls defined by other
// traits.
// This provided grant should follow usual borrowing rules, if possible; that is
// if one &mut grant is provided, then another can not be taken (this is not
// mandatory though, structure is able to handle it internally).
trait PhantomGrant {
type Grant: BufferGrant;
fn grant(&self) -> Self::Grant;
}
// So let's say buffer just wraps Vec<u8> and returns some other type that
// wraps &[u8] and provides some more nice methods defined by BufferGrant trait.
struct Buffer {}
impl PhantomGrant for Buffer {
type Grant = ();
// ^------ Here we have to use our custom type, it can have a
// generic or whatever as long as it provides a compiler
// with type information. Used tuple as an example for
// shorter code.
fn grant(&self) {}
}
// =============================
// Second part.
// =============================
// This is this other trait, that takes Grants as arguments, let's say it uses
// provided grant contents as &[u8] and prints if they equal.
trait DoWork<T> {
type Grant: BufferGrant;
fn do_something(&self, grant: &Self::Grant);
}
impl<T: PhantomGrant> DoWork<T> for String {
type Grant = <T as PhantomGrant>::Grant;
fn do_something(&self, _g: &Self::Grant) {
// So here a string would compare it's contents with provided argument,
// and print something if they equal.
// In real requirements, &mut is used for concatenation, etc., but i
// think it is not relevant for now.
}
}
// These are grants provided methos, let's say it would allow to read vec
// contents through &[u8].
trait BufferGrant {}
impl BufferGrant for () {}
Compilation error:
Compiling playground v0.0.1 (/playground)
error[E0283]: type annotations needed
--> src/main.rs:6:7
|
6 | s.do_something(&grant);
| ^^^^^^^^^^^^
|
= note: cannot satisfy `_: PhantomGrant`
= help: the trait `PhantomGrant` is implemented for `Buffer`
note: required for `String` to implement `DoWork<_>`
--> src/main.rs:34:23
|
34 | impl<T: PhantomGrant> DoWork<T> for String {
| ------------ ^^^^^^^^^ ^^^^^^
| |
| unsatisfied trait bound introduced here
help: try using a fully qualified path to specify the expected types
|
6 - s.do_something(&grant);
6 + <String as DoWork<T>>::do_something(&s, &grant);
|
For more information about this error, try `rustc --explain E0283`.
My questions are - is it possible to use short syntax and how to do it? Or at least get an affirmation that this currently is not possible so i accept this as it is and move on with the task. I am hopeful that maybe there is some clever wrapping or something that could allow to have a clean syntax to library function end users.
Thank you!
1 post - 1 participant
Read full topic
🏷️ Rust_feed