client_rust icon indicating copy to clipboard operation
client_rust copied to clipboard

Allow flattening of a struct through derive(EncodeLabelSet) at any position

Open drbrain opened this issue 2 years ago • 7 comments

Currently when deriving EncodeLabelSet and flattening a struct the flattened struct must appear last, and there must be only one flattened struct, from the test:

#[test]
fn flatten() {
    #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
    struct CommonLabels {
        a: u64,
        b: u64,
    }
    #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
    struct Labels {
        unique: u64,
        #[prometheus(flatten)]
        common: CommonLabels,
    }

    // …

If you place common before unique in struct Labels like this:

#[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
struct Labels {
    #[prometheus(flatten)]
    common: CommonLabels,
    unique: u64,
}

Compilation fails:

error[E0382]: borrow of moved value: `encoder`
   --> derive-encode/tests/lib.rs:147:14
    |
147 |     #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
    |              ^^^^^^^^^^^^^^
    |              |
    |              value borrowed here after move
    |              move occurs because `encoder` has type `LabelSetEncoder<'_>`, which does not implement the `Copy` trait
    |

This occurs because ownership of encoder is given to the flattened struct

I think this would be a breaking change to fix, but fixing it would allow fields to appear in any order, or allow flattening of multiple structs without nesting them all one inside the other in tail position.

drbrain avatar Apr 15 '23 01:04 drbrain

Thanks for debugging and the detailed issue.

I think this would be a breaking change to fix, but fixing it would allow fields to appear in any order, or allow flattening of multiple structs without nesting them all one inside the other in tail position.

Worth exploring passing &mut LabelSetEncoder. Not sure why I chose to require ownership.

Another alternative is to provide a better error message in the derive macro when the flattened property is not the last.

mxinden avatar May 09 '23 04:05 mxinden

Worth exploring passing &mut LabelSetEncoder.

My initial impression is that this would be a welcome API change. If we could impl<A: EncodeLabelSet, B: EncodeLabelSet> EncodeLabelSet for (A, B), that would generally make label composition more flexible.

olix0r avatar Dec 07 '23 02:12 olix0r