ITE meeting agenda

  • Meeting date: 2023-12-14

Attendance

  • People: TC, tmandry

Meeting roles

  • Minutes: TC

Announcements or custom items

(Meeting attendees, feel free to add items here!)

impl-trait-utils variant macro

https://github.com/rust-lang/impl-trait-utils/pull/2

The name

TC: I've mostly reviewed the PR. The implementation looks good. The only open question I had was over the name:

Regarding the name, I agree that variant is a fine thing to call SendIntFactory, but I'm less sure it's the correct part of speech for the attribute proc macro.

It almost seems to be suggesting that variant(..) is some kind of property of IntFactory rather than that we're creating a new trait variant.

Consider, by way of contrast, derive(Copy, Clone). The word derive is a verb, and that helps to make it clear that the attribute is deriving a new thing.

Perhaps we could call this derive_variant?

tmandry: It'd be good for it to be short.

TC: Agreed about that.

TC/tmandry: Perhaps add_variant or make_variant would be options.

tmandry: I like make_variant.

TC: Sounds good to me.

Update README?

TC: Did we want to update the README in this PR also?

tmandry: Yes, we should do that.

Bound on associated types

TC: One question I had reading through is whether or not we'd want to add bounds on the associated type. In a sense we don't need to, because like RTN, the user could add the bounds during use.

tmandry: It's a good question. We could add an attribute over the associated type to control this. It might be overly prescriptive to do by default.

Publishing this to crates.io

TC/tmandry: Do we have a project-managed account for publishing to crates.io?

Looking at:

https://crates.io/crates/libc

It's owned by:

Perhaps we should create a team for rust-lang:async to use as the owner for this. Maybe T-infra handles this?

Looks like we can convert a GitHub team into a crates.io team.

What to name the crate?

It's currently called trait_transformer. That's not correct because trait transformers are meant to be used at the use site, but this has to be used at the definition site. So it's not a polyfil.

We could name it make-variant if we only ever expect that we'll have this one proc macro in the crate.

Do we have a convention on dashes or underscores in the crate name?

Looking at the things owned by rust-lang-owner, it seems like dashes win. E.g. cfg-if and crates-io.

Naming options:

  • trait-variant
  • trait-variants (plurality?)
  • make-variant
  • make-trait-variant (too long)
  • variant-trait
  • trait-utils
    • Gets to questions of scope; this may attract PRs for anything that seems like a valid trait util.
  • trait-polyfils

We might think of this as a polyfil for implementable trait aliases. We could have a version of the macro that doesn't output the trait itself, then you could copy and paste the definition from another crate locally. We would need to have an argument for the path to the real trait, then the macro would insert that for the forwarded function calls.

We may have to think about the effect of the blanket impl there.

Let's go with trait-variant.

Let's look at the full invocation:

#[trait_variant::make_variant(SendFoo: Send)]

It's a bit repetitive, but probably OK.

Extension to dyn

#[make_variant(dyn DynIntFactory: Send)]
#[make_variant(DynIntFactory: dyn + Send)]
#[make_dyn_variant(DynIntFactory: Send)]
#[make_dyn_variant(DynLocalIntFactory)]
#[make_dynable(DynIntFactory: Send)]
trait LocalIntFactory {
    async fn make(&self, x: u32, y: &str) -> i32;
}

Niko has a dyner repo with prototypes.

The async-fundamentals-initiative website has some other ideas.

It expands to a variant of the trait

This has examples:

https://rust-lang.github.io/async-fundamentals-initiative/explainer/async_fn_in_dyn_trait/avoiding_allocation.html#how-you-apply-an-existing-adapter-strategy-to-your-own-traits

Blog post about AFIT/RPITIT

RPITIT is ready, async is not (but it’s getting there)

The proc macro is a part of this story. Now that there is believed to be a path from using this macro to using implementable trait aliases, we're now actually feeling much more positive about this.

Original brainstorm of possibilities
#[bounded(HttpService: Send)]
#[bounded(HttpService where Self: Send, fetch(): Send)]
#[transform(HttpService = Send LocalHttpService)]
#[product(Send => HttpService)]
#[make_variant(HttpService: Send)]
#[send_variant(HttpService)]
#[variant(HttpService: Send)]
#[add_variant(HttpService: Send)]
#[make_variant(HttpService: Send)]
#[with_variant(HttpService: Send)]
#[mutant(HttpService: Send)]
#[mutate(HttpService: Send)]
#[adapt(HttpService: Send)]
#[modify(HttpService: Send)]
#[transform(HttpService: Send)]
trait LocalHttpService {
    async fn fetch(&self, url: Url) -> HtmlBody;
}

Project board issues

"AFIT: impl can't add extra lifetime restrictions, unlike non-async" #104689

"Weird interaction between specialization and RPITITs" #108309

"RPITIT with Send trait marker breaks borrow checker" #111105

"Failed to normalize async_fn_in_trait ICE for indirect recursion of async trait method calls" #112047

"Exponential compile times for chained RPITIT" #102527

"Mysterious "higher-ranked lifetime error" with async fn in trait and return-type notation" #110963

"AFIT: strange errors on circular impls" #112626

"Nightly (warning): Async traits Self return requires type specification" #113538

"hrtb + infer types break auto traits with return type notation " #109924

"async_fn_in_trait and return_type_notation cause awkward awaits" #112569

Pending PRs on the impl-trait-initiative repo

None.

Open PRs

"stricter hidden type wf-check" rust#115008

"rework opaque type region inference" rust#116891

"Prevent opaque types being instantiated twice with different regions within the same function" rust#116935