Skip to content

Experiment with ergonomic ref-counting #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 of 8 tasks
nikomatsakis opened this issue Jul 22, 2024 · 9 comments
Open
5 of 8 tasks

Experiment with ergonomic ref-counting #107

nikomatsakis opened this issue Jul 22, 2024 · 9 comments

Comments

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Jul 22, 2024

Metadata
Point of contact @spastorino
Team(s) lang
Goal document 2025h1/ergonomic-rc

Summary

  • Deliver a nightly implementation of the experimental use syntax for ergonomic ref-counting.
  • RFC decision on the above

Tasks and status

  • Implementation (@spastorino)
  • Reviews (@nikomatsakis)
  • Lang-team champion (lang Team)
  • Author RFC (@joshtriplett)
  • Introduce x.use and use || syntax and UseCloned trait (Ergonomic ref counting rust#134797).
  • Modify codegen so that we guarantee that x.use will do a copy if X: Copy is true after monomorphization. Right now the desugaring to clone occurs before monomorphization and hence it will call the clone method even for those instances where X is a Copy type.
  • Convert x.use to a move rather than a clone if this is a last-use.
  • Make x equivalent to x.use but with an (allow-by-default) lint to signal that something special is happened.
@nikomatsakis
Copy link
Contributor Author

This issue is intended for status updates only.

For general questions or comments, please contact the owner(s) directly.

@rust-lang rust-lang locked and limited conversation to collaborators Jul 25, 2024
@nikomatsakis
Copy link
Contributor Author

This issue has not seen many updates, but there has been definite progress:

@fmease fmease marked this as a duplicate of rust-lang/rust#133795 Dec 3, 2024
@nikomatsakis
Copy link
Contributor Author

Year-end summary:

In 2024H2 @spastorino began work on an experimental implementation (not yet landed) and @joshtriplett authored a corresponding RFC (rust-lang/rfcs#3680), which has received substantial feedback.

We opened a proposed 2025H1 project goal to continue by (a) landing the experimental branch and (b) addressing feedback on the RFC, reading it with the lang-team, and reaching a decision.

@nikomatsakis nikomatsakis modified the milestones: 2024h2, 2025h1 Feb 18, 2025
@nikomatsakis
Copy link
Contributor Author

This is a continuing project goal, and the updates below this comment will be for the new period 2025h1

@spastorino
Copy link
Member

There's a PR up rust-lang/rust#134797 which implements the proposed RFC without the optimizations.
The PR is not yet merged and we need to continue now working on addressing comments to the PR until is merged and then start implementing optimizations.

@nikomatsakis nikomatsakis changed the title Ergonomic ref-counting Experiment with ergonomic ref-counting Feb 26, 2025
@nikomatsakis nikomatsakis removed their assignment Feb 26, 2025
@nikomatsakis nikomatsakis moved this to Project goal in Lang team features Mar 4, 2025
@nikomatsakis
Copy link
Contributor Author

nikomatsakis commented Mar 17, 2025

Update: rust-lang/rust#134797 has landed.

Semantics as implemented in the PR:

  • Introduced a trait UseCloned implemented for Rc and Arc types.
  • x.use checks whether x's type X implements the UseCloned trait; if so, then x.use is equivalent to x.clone(), otherwise it is a copy/move of x;
  • use || ...x... closures act like move closures but respect the UseCloned trait, so they will either clone, copy, or move x as appropriate.

Next steps:

  • Modify codegen so that we guarantee that x.use will do a copy if X: Copy is true after monomorphization. Right now the desugaring to clone occurs before monomorphization and hence it will call the clone method even for those instances where X is a Copy type.
  • Convert x.use to a move rather than a clone if this is a last-use.
  • Make x equivalent to x.use but with an (allow-by-default) lint to signal that something special is happened.

Notable decisions made and discussions:

  • Opted to name the trait that controls whether x.use does a clone or a move UseCloned rather than Use. This is because the trait does not control whether or not you can use something but rather controls what happens when you do.
  • Question was raised on Zulip as to whether x.use should auto-deref. After thinking it over, reached the conclusion that it should not, because x and x.use should eventually behave the same modulo lints, but that (as ever) a &T -> T coercion would be useful for ergonomic reasons.

@nikomatsakis
Copy link
Contributor Author

TL;DR: There is now an early prototype available that allows you to write x.use; if the type of X implements UseCloned, then this is equivalent to x.clone(), else it is equivalent to a move. This is not the desired end semantics in a few ways, just a step along the road. Nothing to see here (yet).

@nikomatsakis
Copy link
Contributor Author

In reviewing rust-lang/rust#138628, we realized that the tests were not behaving as expected because they were running in Rust 2015 which had distinct capture rules. My suggestion was to limit the use keyword (or at least use closures...) to Rust 2021 so as to avoid having to think about how it interacts with earlier capture rules (as well as potential migrations). I believe this follows from the Edition axiom that Editions are meant to be adopted.

There is an interesting tension with Rust should feel like one language. My feeling is that there is a missing tenet: the reason we do editions and not fine-grained features is because we wish to avoid combianotoric explosion, where odd combinations of features can lead to untested scenarios. But that is exactly what would be happening here if we allow use on older editions. So I think the rule should be that you make new features available on older editions up until the point where they interact with something that changed -- in this case, use closures interact with the closure capture rules which changed in Rust 2021, so we should limit this feature to Rust 2021 and newer.

Put another way, you should never have to go back and modify an edition migration to work differently. That suggestions you are attempting to push the feature too far back.

@spastorino
Copy link
Member

We've modified codegen so that we guarantee that x.use will do a copy if X: Copy is true after monomorphization. Before this change the desugaring to clone occured only before monomorphization and hence it would call the clone method even for those instances where X is a Copy type. So with this modification we avoid such situation.

We are not working on convert x.use to a move rather than a clone if this is a last-use.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Status: Project goal
Development

No branches or pull requests

4 participants