• BB_C
      link
      fedilink
      arrow-up
      1
      ·
      22 hours ago

      Stating the obvious: a trait is type class you implement for types. It’s not something you can “pin metadata” (or any data) to.

      • orclev@lemmy.world
        link
        fedilink
        arrow-up
        3
        ·
        20 hours ago

        It’s an API, if you add methods to it then the implementations will support that. That is in fact the entire point of a trait.

        • BB_C
          link
          fedilink
          arrow-up
          1
          ·
          12 hours ago
          struct SomeFuture;
          
          impl Future for SomeFuture {
            // ....
          }
          
          

          where are you going to “pin metadata”?

          • lad
            link
            fedilink
            English
            arrow-up
            3
            ·
            12 hours ago

            I think, they mean:

            pub trait Future {
              // ....
            
              fn put_metadata(...);
            
              fn get_metadata(...);
            }
            

            I find it too magical to be necessary, but I can see how it might be useful. This can be achieved with a wrapper, but will then require you to wrap every future, which is not too convenient

            • BB_C
              link
              fedilink
              arrow-up
              1
              ·
              8 hours ago

              It’s not about magic, it’s just not how the abstraction works.

              Let’s have a concrete example, poem::web::Data utilizes opentelemetry::context::FutureExt which has the trait methods with_context() and with_current_context(). But where is the data/context actually stored? In the WithContext struct of course. Because there is no such a thing as pinning (meta)data to a trait.

              @[email protected] ^^

              • orclev@lemmy.world
                link
                fedilink
                arrow-up
                1
                ·
                7 hours ago

                You do realize FutureExt is a trait right? That’s literally what I’m asking for just with it baked into Future instead of FutureExt.

                • BB_C
                  link
                  fedilink
                  arrow-up
                  1
                  ·
                  5 hours ago
                  • Rust doesn’t do implicit transparent structs. The FutureExt trait methods return a wrapper struct WithContext which is where the data (T) and the context are stored. One method takes context directly from an argument, the other clones one from a thread local. Data can’t hang in thin air to be attached to a triat. This also shows that the abstraction you (presumably) were asking about is both possible and already exists.
                  • Forcing a context on all T: Future types would make the abstraction non-zero-cost in any case.
                  • orclev@lemmy.world
                    link
                    fedilink
                    arrow-up
                    1
                    ·
                    3 hours ago

                    You’re really hung up on the fact I said “pin metadata to a Future”. I didn’t mean that literally, but conceptually. The Future trait defines the API, and what I’m asking for is for that API to provide a mechanism to retrieve a context object that can be used to store arbitrary data. It’s almost there already. The Context that poll takes has a pub const fn ext(&mut self) -> &mut (dyn Any + 'static) method already (although I’m not thrilled by the type signature, I’d prefer it have an associated type or generic letting you define your own concrete extension type), it’s just that by being associated to Wake instead of Future it makes it impractical to use for storing and retrieving metadata when working with Futures.

                    There’s a few ways that the problem could be approached from. One option would be to add a new associated type to Future for an arbitrary context object. If you don’t need it you could always just set it to () same as is done for the Output type. There might be a clever way to re-use the task Context object that Wake has although I’m not sure how that would be done. Could also define a new standard trait similar to how FutureExt does things (maybe something like ContextualFuture), but that’s less useful for exactly the reason you pointed out, that Rust doesn’t do implicitly transparent structs.

                    You can stop repeating that traits don’t literally store data, everyone already knows that. Everyone knew that from the beginning. Repeating that again and again serves no purpose at all. Nobody is asking to literally store data on a trait.

                    Fundamentally the issue is that Future is a n+m model where you have n virtual threads executing on m OS threads. As such traditional solutions to associating data to OS threads like thread locals don’t work as there’s no guarantee that a given virtual thread will continue to execute on any given OS thread. Many languages have faced this exact problem and the solution that’s been arrived at in nearly every case is to add an associated execution context (in a variety of ways) that can be queried for from the runtime and used to store the equivalent of “thread local” data. That’s literally what I’m asking for, but in a way that’s part of the standard API so you don’t need to be tightly coupled to a specific async runtime. It is a problem that comes up repeatedly which is why things like FutureExt exist, but it should be part of the standard, not something ad hoc that everyone keeps having to solve on their own.

            • devnev@lemmy.dbzer0.com
              link
              fedilink
              arrow-up
              2
              ·
              9 hours ago

              Other languages have ended up introducing it out of practical necessity, e.g. Go’s contexts, JS execution contexts. Pick your poison, although I expect Rust’s general minimal approach will leave it as extra parameters, Go-style.