EDIT: This proposal is currently withdrawn, and I think a variation of RFC PR 248 is a better solution for the problems at hand. But
~ as a semi-explicit coercion operator can still be added later for user definable coercion rules, if they are implemented in Rust in the future.
Rust prefers to be explicit, but there are times when being too explicit can be ergonomic problems. Particularly, recently we are talking about introducing more coercions into the language:
Also discussions about introducing a
The problems of implicit coercions is they may be too implicit. When we see a function call
foo(bar, baz);, we will not be sure if the compiler is moving
baz, or taking their references, or launching nuclear missiles even before the body of
foo gets executed.
This goes against Rust’s philosophy.
So, being too explicit and too implicit are both undesirable sometimes, then what to do?
Say we have a function
fn foo(bar: &T), and a value
fancy: Very<Deep<Chain<Of<Wrappers<T>>>>>, and we want to apply
foo to the “meaningful” content of
We can do it explicitly,
foo(&*****fancy), or implicitly with proposed implicit coercions:
Both have their own problems. But usually the programmer doesn’t really care about exactly how many
*'s he/she has to write, all he/she wants to know is that “some deferencing/coercions are happening and I may have to be cautious”.
So I propose we introduce a sigil for saying “some coercion magic happens here”, just like how
! in macros means “some code transformation magic happens here”.
And that sigil would be
~. The rule is:
- the language can define arbitrary coercion rules, even make them user-definable with a trait, but the only coercion rule that the language implicitly applies is auto dereferencing self in method calls;
- when a value is used in a position where possible coercions can be applied, the programmer must opt-in with
~, a prefix unary operator;
- it is a compile error to use successive
~s or use it when no coercion rules can apply.
So we can say
~? It is unused and lightweight, and implies “slight transformations” in my eyes.
~? Because some keyboard layouts do not have a
Personally I believe this is a good compromise between “no coercions” and “implicit coercions”.
Also, I think
~ can help with a problem introduced by auto dereferencing
self in method calls:
If we have a
bar: Rc<Foo>, when we call
bar.clone(), which clone are we calling?
I propose that we use
~ as a “reverse coercion” operator in the suffix position here. The rules are:
foo.bar()always calls the
barmethod on the “meaningful content”;
- if we want to call a
barmethod on some wrapper along the auto-deref chain, we use the syntax:
- if there are multiple
bars defined in the wrappers along the chain,
foo~.bar()causes a compile error.
- Further disambiguation should be done with features like UFCS.
Also a good compromise in my eyes.
So, do you think these are good ideas or not?