rust-lang / rust-lang/rfcs

Add a Cow "operator" (not a replacement to the current Cow type), and some syntax sugar for performance.

Open
#2,448 6 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-lang T-libs
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

Forked off #2447 .

As mentioned in #2447 there are many times where you wish the compiler could be smarter. The solution proposed in #2447 is to simply add an explicit method where you can tell the compiler "optimize it like this". It's very verbose.

While we don't have that (altho it's definitely the easier solution), I'm also gonna suggest a slightly more powerful... thing, that would make future Rust a lot less verbose: Cow "operator".

This Cow, unlike std::borrow::Cow, would go in std::ops::Cow. I'm not sure what its final form would look like, but a good starting point is:

enum Cow<'a, T> {
    Owned(T),
    Borrowed(&'a T)
}

Note that it's not so weird for this to be in std::ops - it's not introducing an operation on objects, exactly, but it's more akin to the range "operator" and friends.

This Cow can then be used in method definitions:

#[inline]
fn to_ascii_lowercase(mut self: std::ops::Cow<Self>) -> Self {
    // this method implementation is probably not gonna be the final form, but is a good starting point.

    self.make_owned(); // the compiler knows about this method!
    self.make_ascii_lowercase();
    self
}

Now as you can see, this is a fairly reasonable method definition, there's nothing weird about it (except the Cow<Self>). It's also something the compiler can heavily optimize in the Owned case (as it knows that make_owned would be a no-op), which is really important because in this case the compiler is allowed to look at that case even in the Borrowed case. For example, if you had:

let str_up = String::from("Hello World!");
let str_lo = su.to_ascii_lowercase();
let count = str_lo.len();
mem::drop(str_up); // explicitly move/use str_up somewhere

In current Rust, i.e. without being able to look at that case, the compiler has to do an allocation and a deallocation for str_up and another for str_lo. Whereas with the Cow "operator", Rust would be able to infer (by looking through make_ascii_lowercase) that str_lo.len() is equivalent to str_up.len() (note that this wouldn't be possible for Unicode to_lowercase and to_uppercase), and thus optimize the allocation and deallocation away!

In another case, let's say you instead have:

let str_up = String::from("Hello World!");
mem::drop(str_up.to_ascii_lowercase());
// never use str_up again, and let it drop automatically

Rust would be able to infer you never use str_up again, and rather than passing to_ascii_lowercase a borrowed str_up, it would move str_up into an Owned! This also optimizes the allocation and deallocation away, but unlike the previously mentioned artificial use-case, this one is a very real use-case.

So why's it an op? The main thing for it being an op is that it would be used for compiler inference tricks. I prefer adding it as a type rather than a syntax feature (fn(cloned self) comes to mind) because it's seemingly easier to learn special types than it is to learn new syntax. (And how would you represent it in fn types, anyway?)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the linked issue #2447 and the proposed std::ops::Cow examples, including the ownership and optimization cases described here. Determine the operator's final form, compiler behavior, and relationship to the existing std::borrow::Cow; done means a decided, implementable design rather than an unresolved proposal.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.