Rust Async Working Group
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # Deep dive notes: AFIT case studies Link to document: * [Async Builder + Provider API Case Study ](https://github.com/compiler-errors/async-fundamentals-initiative/blob/provider-api/evaluation/case-studies/builder-provider-api.md) * [Microsoft Async Case Study](https://hackmd.io/@eholk/S1LZmEXW3) * [Netstack3 Async Socket Handler Case Study ](https://github.com/akonradi/async-fundamentals-initiative/blob/netstack3-case-study/evaluation/case-studies/socket-handler.md) ###### tags: `deep-dive` --- ## Notes from embassy links to uses of async functions in traits within Embassy: * most popular ones are [embedded-hal-async](https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal-async/src) * HAL crates provide impls for particular microcontrollers (e.g., [gpiote](https://github.com/embassy-rs/embassy/blob/master/embassy-nrf/src/gpiote.rs#L518), [spim](https://github.com/embassy-rs/embassy/blob/master/embassy-nrf/src/spim.rs#L523), [i2c](https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/i2c/v2.rs#L1061)) * driver crates use the traits to [implement a driver for some chip that works on top of any HAL: * [nrf70](https://github.com/embassy-rs/nrf70/blob/main/src/main.rs#L811) (that one is interesting because it defines another async Bus trait on top, because that chip can be used with either SPI or QSPI) * [es-wifi-driver](https://github.com/drogue-iot/es-wifi-driver/blob/main/src/lib.rs#L132) * [hts221](https://github.com/drogue-iot/hts221-async/blob/main/src/lib.rs#L40) * [sx127x](https://github.com/embassy-rs/embassy/blob/master/embassy-lora/src/sx127x/sx127x_lora/mod.rs#L50) * there's also embedded-io, which is [std::io traits adapted for embedded](https://github.com/embassy-rs/embedded-io/blob/master/src/asynch.rs) * HALs have [impls for serial ports](https://github.com/embassy-rs/embassy/blob/master/embassy-nrf/src/buffered_uarte.rs#L600) * embassy-net has an [impl for TCP sockets](https://github.com/embassy-rs/embassy/blob/master/embassy-net/src/tcp.rs#L431) * here's some [driver using it](https://github.com/drogue-iot/esp8266-at-driver/blob/main/src/lib.rs#L74) * embassy-usb has a [Driver trait](https://github.com/embassy-rs/embassy/blob/master/embassy-usb-driver/src/lib.rs); that one is probably the most complex, it's an async trait with associated types with more async traits, and interesting lifetimes * HALs [impl these traits for one particular chip](https://github.com/embassy-rs/embassy/blob/master/embassy-nrf/src/usb/mod.rs#L178) and embassy-usb uses them to [implement a chip-independent USB stack](https://github.com/embassy-rs/embassy/blob/master/embassy-usb/src/lib.rs#L188) most of these are "abstract over hardware", and when you build a firmware for some product/board you know which actual hardware you have, so you use static generics, no need for dyn the few instances I've wished for dyn is: * with embedded-io it does sometimes happen. For example, running the same terminal ui over a physical serial port and over telnet at the same time. Without dyn that code gets monomorphized two times, which is somewhat wasteful. * this trait https://github.com/embassy-rs/embassy/blob/master/embassy-usb/src/lib.rs#L89 . That one MUST use dyn because you want to register multiple handlers that might be different types. Sometimes it'd have been handy to be able to do async things within these callbacks. Workaround is to fire off a notification to some other async task, it's not been that bad. * niko: how is this used? * handlers are added [here](https://github.com/embassy-rs/embassy/blob/master/embassy-usb/src/builder.rs#L262), passed into UsbDevice [here](https://github.com/embassy-rs/embassy/blob/master/embassy-usb/src/lib.rs#L225), and then called when handling some bus-related stuff, for example [here](https://github.com/embassy-rs/embassy/blob/master/embassy-usb/src/lib.rs#L714-L715). * the tldr of what it's used for is you might have a "composite" usb device, which can have multiple "classes" at the same time (say, an Ethernet adapter and a serial port). Each class gets its own "endpoints" for data, so each launches its own independent async tasks reading/writing to these endpoints. * But there's also a "control pipe" endpoint that carries "control" requests that can be for any class for example for ethernet there's control requests for "bring the ethernet interface up/down", so each class registers a handler with callbacks to handle their own control requests, there's a "control pipe" task that dispatches them. * Sometimes when handling them, you want to do async stuff. For example for "bring the ethernet interface up" you might want to do some async SPI transfer to the ethernet chip, but currently you can't. * niko: would all methods be async if you could? * not sure if all methods, but probably `control_in`/`control_out` yes. and about where to store the future for the dyn... not sure. That crate is no-alloc so Box is out it'd probably be inline in the stack, like with StackFuture. Would need configuring the max size, probably some compile-time setting, or a const-generic in UsbDevice. --- Leave questions, observations, discussion topics below. --- ## dyn, rtn, send, etc nikomatsakis: The Microsoft case study says > The `#[async_trait]` limitation will likely go away almost immediately once the RTN PR merges, since it can be updated to support the new syntax. Still, this experience does highlight one thing, which is that the DynTrait workaround requires us to commit up front to whether that trait will guarantee Send futures or not. There does not seem to be an obvious way to push this decision to the use site like there is with Return Type Notation. I *think* this is highlighting an existing challenge with dyn -- i.e., today, if I write an iterator: ```rust struct MyIteratorOp<I: Iterator> { base_iter: I } ``` and then I do `some_base_iter.my_iterator_op()`, the resulting iterator type (`MyIteratorOp<SomeBaseIter>`) will be `Send` iff `SomeBaseIter` is `Send`. But if I were to write `MyIteratorOp` to use dyn dispatch: ```rust struct MyIteratorOp<T> { base_iter: Box<dyn Iterator<Item = T>> } ``` then `MyIteratorOp` would *never* be send, unless I commit up front by making it `dyn Iterator + Send`. Is this the same general problem encountered, or is there some async specific twist to it? I think it's a definite footgun we should think about how to solve, but I also think it's an orthogonal point from send bounds in AFIT in general. eholk: I think for me the main realization here is that there's a version of the Send bound problem for AFIDT too, although I agree with you that it seems more like a limitation of dyn rather than AFIT in particular. I wonder if we could have RTN push the extra bounds into the `dyn*` that gets generated for dyn async traits? e.g. ```rust= fn foo(x: &dyn Foo<bar(): Send) { ... } ``` becomes something like ```rust fn foo(x: &dyn Foo<bar() = dyn* BarTrait + Send>) { ... } ``` The coercion story wouldn't be great though, because you have to remember to put Send bounds all the way up the stack. nikomatsakis: yes, this is what tmandry and I intended had discussed in the past, or something like it. Yosh (galaxy brain): Could we think of the `dyn` + `Send` definition as (yet another) effect composition problem? nikomatsakis: I have wondered same thing... certainly feels similar. i.e., being able to make the "send version" of a type and have that propagate down. --- ## Yosh told me you disliked RTN, eholk nikomatsakis: I was surprised by how positive the microsoft case study sounded because yosh hinted to me that RTN was more painful than expected. I was expecting to read that it was annoying because we had to repeat bounds a lot in some trait with a lot of methods. There was a hint of those, i.e., the trait had 2 methods. Was this the point of ergonomic pain or was there something else? eholk: I wrote this right after trying RTN, but after some time I felt more negative about it. eholk: One thing was that before we had the dyn version that used async-trait with a blanket impl. Since async trait didn't support RTN, I had to rewrite the whole thing to return boxes. Async trait will fix this. But having to do that was annoying. eholk: A lot of punctuation you have to type. `(..): Send` etc, and you have to repeat it for every function. It surprised me to see lower-case letters, e.g. `Foo<blah(): Send>`. I'd like to try one of the more coarse grained things like trait transformers. RTN seemed overly verbose. nikomatsakis: My favored syntax is `Foo<bar(): Send, baz(): Send>`. nikomatsakis: I also imagined us shipping a proc macro that would create the dyn + a send alias. nikomatsakis: it sounds like the min version of this feedback is that we need to have the macro or it's going to be super annoying. eholk: can we build the macro without stabilizing RTN? nikomatsakis: by building it into the compiler, this is what we called the tmandry special, but I tend to think we want RTN anyway -- i.e., stabilizing the building block lets people use other trait bounds besides Send or other things. yoshuawuyts: I have other use cases for RTN besides this one; I think it's a good primitive to make available. tmandry: it sounds like you have a use case that is not addressed by trait transformers? yoshuawuyts: correct. --- nikomatsakis: So * Fuchsia worked awesome, able to refactor away Send bound needs * AWS worked fine, would like dyn * Microsoft doing more complicated stuff surfaced that RTN was kind of an annoying primitive, also would like dyn eholk: Some of the Send bounds might've been accidental from use of `async_trait` ---

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully