Rust generic AddAssign with references - rust

A while ago I looked into writing a generic iterator for the Fibonacci sequence
that could accept both primitive numbers as well as custom types (such as
bignums). After failing to get a version working for both the primitive types
and bignums, I stumbled upon this question:
How to write a trait bound for adding two references of a generic type?
Which used so called Higher Ranked Trait Bounds to solve the problem with this
particular issue.
Now however, I'm trying to use a similar strategy to use the *_assign
operators instead. In particular, I'm trying to get something similar to this
working:
use std::ops::{Add, AddAssign};
fn add_test<'a, T>(x: &'a T, y: &'a T) -> T
where
for<'b> &'b T: Add<Output = T>,
{
x + y
}
fn add_assign_test<'a, T>(x: &'a mut T, y: &'a T) -> T
where
for<'b> &'b mut T: AddAssign<&'b T>,
T: Clone,
{
x += y;
x.clone()
}
fn main() {
println!("add_test()={}", add_test(&1, &2));
println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
}
add_test() works as expected but I'm unable to get add_assign_test() to work in a similar way. The errors I'm getting suggest that there might not actually exist an implementation for this kind of behaviour on the primitive types:
error[E0277]: the trait bound `for<'b> &'b mut _: std::ops::AddAssign<&'b _>` is not satisfied
--> src/main.rs:21:38
|
21 | println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
| ^^^^^^^^^^^^^^^ no implementation for `&'b mut _ += &'b _`
|
= help: the trait `for<'b> std::ops::AddAssign<&'b _>` is not implemented for `&'b mut _`
= note: required by `add_assign_test`
I could create a macro that creates implementations for these operators that actually takes references to the primitive types, but that seems a little wasteful. Is there any other way to achieve the same effect?

Just a tiny oversight in your code. Let's look at the trait:
pub trait AddAssign<Rhs = Self> {
fn add_assign(&mut self, rhs: Rhs);
}
The receiver of the method is already &mut self and not self. The reason that you had to do the extra work with Add is because it accepts self as receiver. For AddAssign this means: if a type T implements AddAssign, you can call the method add_assign() on a &mut T!
Thus, instead of writing:
where for <'b> &'b mut T: AddAssign<&'b T>,
... you would write:
where for <'b> T: AddAssign<&'b T>,
(No other line changed so far)
However, you notice that the code still won't compile:
error[E0277]: the trait bound `for<'b> {integer}: std::ops::AddAssign<&'b {integer}>` is not satisfied
--> src/main.rs:13:38
|
13 | println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
| ^^^^^^^^^^^^^^^ no implementation for `{integer} += &'b {integer}`
|
= help: the trait `for<'b> std::ops::AddAssign<&'b {integer}>` is not implemented for `{integer}`
= note: required by `add_assign_test`
The reason is simple: there is simply no implementation of AddAssign for primitive types which takes an immutable reference as rhs (Docs). I don't know if this is an oversight -- it could be worth opening an issue on the Rust repo.
To verify the above code works, I write my own type and implemented AddAssign appropriately: Playground.

Corrected the code snippet based on Lukas' reply:
use std::ops::{Add, AddAssign};
fn add_test<'a, T>(x: &'a T, y: &'a T) -> T
where
for<'b> &'b T: Add<Output = T>,
{
x + y
}
fn add_assign_test<'a, T>(x: &'a mut T, y: &'a T) -> T
where
for<'b> T: AddAssign<&'b T>,
T: Clone,
{
*x += y;
x.clone()
}
fn main() {
println!("add_test()={}", add_test(&1, &2));
println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
}
It appears that this is an issue in Rust itself. There is currently a tracker for this issue.
Until this is fixed, there's two possible workarounds:
Create named-tuples for each primitives and implement OpAssign for those types instead. This does however force you to 'cast' all primitives to your custom type.
Duplicate the 'generic' code with specializations for the primitives.

Related

How to convert a generic function with lifetimes into a function pointer

This is of course a simplified version of my actual problem.
fn my_func<'a, 'b>(a: &'a i32, b: &'b i32) -> i32 {
a + b
}
fn my_func_generic<'a, 'b, T>(a: &'a T, b: &'b T) -> T
where
&'a T: std::ops::Add<&'b T, Output = T>,
{
a + b
}
fn apply_function(x: &i32, y: &i32, function: fn(&i32, &i32) -> i32) -> i32 {
function(x, y)
}
fn main() {
let x = 10;
let y = 11;
println!("{}", my_func(&x, &y));
println!("{}", my_func_generic(&x, &y));
println!("{}", apply_function(&x, &y, my_func));
println!("{}", apply_function(&x, &y, my_func_generic));
}
error[E0308]: mismatched types
--> src/main.rs:23:43
|
23 | println!("{}", apply_function(&x, &y, my_func_generic));
| ^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's> fn(&'r i32, &'s i32) -> _`
found fn pointer `fn(&i32, &i32) -> _`
The question I have is: How can I use my_func_generic as a function pointer to pass it into apply_function?
It can definitely be used as such a function, as println!("{}", my_func_generic(&x, &y)) demonstrates.
Trying to write it in a pointer gives the same error:
let function_pointer: fn(&i32, &i32) -> i32 = my_func_generic;
Annotating generic types manually gives the same error:
let function_pointer: fn(&i32, &i32) -> i32 = my_func_generic::<'_, '_, i32>;
Sadly I don't understand the error message, and don't have enough knowledge about the inner type system of Rust generics to understand how I could solve this issue, or if it's simply not possible due to some mechanism yet unknown to me.
TL;DR: In your case, you can do it as follows:
fn apply_function<'a, 'b>(x: &'a i32, y: &'b i32, function: fn(&'a i32, &'b i32) -> i32) -> i32
But in general, this is impossible.
There are two kinds of lifetimes in Rust: late-bound and early-bound. The difference between the two boils to when we bind the generic lifetime to a concrete lifetime.
For early-bound lifetime, we bind them when you're referring to their function. For late-bound lifetimes, referring to their function gives you a function pointer (or item) generic over the lifetime - what we call HRTB (for<'lifetime> fn(...)), and we choose the actual lifetime only when you call them.
The important point is that any constraints on the lifetime turns it into an early bound lifetime. This is because it is generally impossible to express constrained lifetimes as HRTB (more details on the above linked rustc-dev-guide page), although to be honest I still don't fully understand the reason.
So in my_func_generic(), 'a and 'b are early bound. However, apply_function() expects them to be late-bound (since the default desugaring for elided lifetimes in function pointers is HRTB, fn(&i32, &i32) -> i32 is actually for<'a, 'b> fn(&'a i32, &'b i32) -> i32), and so this is a type mismatch.
In this case, you can just change apply_function() to bind the lifetimes as parameters, as I suggested above. This will still accept late-bound lifetimes, as we'll just bind them immediately. However, as far as I know, in general it is impossible to convert an early-bound lifetime to a late-bound one.
It works if you change your trait bounds slightly:
fn my_func_generic<'a, 'b, T>(a: &'a T, b: &'b T) -> T
where
T: Copy + std::ops::Add<Output = T>,
{
*a + *b
}

How to use non-'static trait objects with associated types?

I have this type:
struct Wrap<T>(Vec<T>);
I want to implement std::ops::Index and return references to trait objects. This was my first attempt (Playground):
use std::ops::Index;
use std::fmt::Display;
impl<T> Index<usize> for Wrap<T>
where
T: Display
{
type Output = Display;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
This doesn't work and leads to this error:
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:13:9
|
7 | impl<T> Index<usize> for Wrap<T>
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
13 | &self.0[index]
| ^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/main.rs:13:9
|
13 | &self.0[index]
| ^^^^^^^^^^^^^^
I think I know why this happens: type Output = Display is equivalent to type Output = Display + 'static as every trait object carries a lifetime bound which defaults to 'static.
So now I can just add the 'static bound to my parameter T, but this is over-constrained I think. I can easily implement such a method when not using an associated type:
impl<T> Wrap<T>
where
T: Display,
{
fn my_index(&self, index: usize) -> &Display {
&self.0[index]
}
}
No 'static bound needed, because now the signature desugars to:
fn my_index<'a>(&'a self, index: usize) -> &'a Display + 'a
Which makes sense: the trait object has to live for at least 'a. (Playground with all the code).
But can I make this work using associated types (like with the Index trait)? I have the feeling that this might work with generic associated types, but (a) I'm not sure and (b) they are not implemented yet.
One attempt is to attach a lifetime to the impl:
// Note: won't work.
impl<'a, T> Index<usize> for Wrap<T>
where
T: Display + 'a,
{
type Output = Display + 'a;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
However, the compiler will not accept it because 'a is not used.
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:7:6
|
7 | impl<'a, T> Index<usize> for Wrap<T>
| ^^ unconstrained lifetime parameter
There are several solutions suggested by the error code E0207, but since we cannot change the Index trait, the only acceptable solution is to make Wrap capture that unconstrained lifetime parameter:
use std::ops::Index;
use std::fmt::Display;
use std::marker::PhantomData;
struct Wrap<'a, T>(Vec<T>, PhantomData<&'a ()>);
// ^~ ^~~~~~~~~~~~~~~~~~~
impl<'a, T> Index<usize> for Wrap<'a, T>
where
T: Display + 'a,
{
type Output = Display + 'a;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
fn main() {
let w = Wrap(vec!['a', 'b'], PhantomData);
println!("{}", &w[0]); // prints "a"
let s = "hi".to_string();
let w = Wrap(vec![&s], PhantomData);
println!("{}", &w[0]); // prints "hi"
}
(Playground)
For sure, this will change your API and that extra lifetime will infect everywhere... If this is not acceptable, you could either
Not use the Index trait, introduce your own lifetime-sensitive trait instead (thus users will need to use w.my_index(i) instead of &w[i]); or
Set Output = Display + 'static, and exclude all transient types. Users will need to clone or use Rc.
Return a reference to T instead of returning a reference to a trait object and let the user cast to a trait object, or just let Rust implicitly infer from the context when to perform the cast:
use std::fmt::Display;
use std::ops::Index;
fn main() {
let w1 = Wrap(vec!['I', 'b']);
let s = "am".to_string();
let w2 = Wrap(vec![&s]);
let w3 = Wrap(vec![1, 2]);
let mut trait_store: Vec<Box<Display>> = Vec::new();
trait_store.push(Box::new(w1.index(0)));
trait_store.push(Box::new(w2.index(0)));
trait_store.push(Box::new(w3.index(0)));
for el in trait_store {
println!("{}", el);
}
}
struct Wrap<T>(Vec<T>);
impl<T> Index<usize> for Wrap<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
Hi I met the same problem as you. "Like &Index<usize, Output = Display>. This doesn't work with Index directly, but using Index in my question made it a bit easier."
I didn't find out whether the Rust releases some related features or not. But I figure out a rather foolish way to fulfill my demands.
This method only works when the structs which implement the trait are enumerable. Suppose that you have three structs Index1, Index2, Index3, they all implement the trait Index<usize, Output = Display>
Then we can simply wrap these structs by
pub enum Indices{
Index1(Index1),
Index2(Index2),
Index3(Index3),
}
And then implement the trait for the enum and all of its variants, there is an example for this:
rust - How do I implement a trait for an enum and its respective variants? - Stack Overflow

Confused about forwarding a reference through multiple functions

I'm having trouble understanding how references get forwarded through functions. The following scenario seems to compile as expected:
trait Trait {}
struct ImplementsTrait {}
impl Trait for ImplementsTrait {}
fn foo(t: &mut Trait) {
// ... use the mutable reference
}
fn forward(t: &mut Trait) {
foo(t); // forward the type '&mut Trait' to foo
}
fn main() {
let mut t = ImplementsTrait{};
forward(&mut t); // need to pass as reference because Trait has no static size
}
However, in using the API for the capnp crate, I get unexpected behavior:
fn parse_capnp(read: &mut BufRead) {
let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
Ok(())
}
fn main() {
// ... ///
let mut br = BufReader::new(f);
parse_capnp(&mut br);
Ok(())
}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:18:16
|
18 | let reader = serialize_packed::read_message(read, message::ReaderOptions::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
The signature of read_message is:
pub fn read_message<R>(
read: &mut R,
options: ReaderOptions
) -> Result<Reader<OwnedSegments>>
where
R: BufRead,
It appears that read is getting passed by value when it is a &mut BufRead and read_message is expecting a &mut BufRead. The only way to get this snippet to compile for me is changing this to:
fn parse_capnp(mut read: &mut BufRead) {
let reader = serialize_packed::read_message(&mut read, message::ReaderOptions::new());
Ok(())
}
I believe I am missing something simple about the types here. To me, this appears to pass a &mut &mut BufRead, which is not the expected type, but compiles.
Could someone add clarity to the types of read and t for the two examples?
I've looked at the following threads:
Use of mut in function signature
What are Rust's exact auto-dereferencing rules?
For the first thread, I'd say the comparison to C-style pointers is faulty due to the dereferencing rules that Rust applies.
Creating a Minimal, Complete, and Verifiable example that reproduces the problem is a useful step:
use std::io::BufRead;
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
{}
fn parse_capnp(read: &mut BufRead) {
read_message(read);
}
fn main() {}
error[E0277]: the trait bound `std::io::BufRead: std::marker::Sized` is not satisfied
--> src/main.rs:9:5
|
9 | read_message(read);
| ^^^^^^^^^^^^ `std::io::BufRead` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::io::BufRead`
note: required by `read_message`
--> src/main.rs:3:1
|
3 | / pub fn read_message<R>(read: &mut R)
4 | | where
5 | | R: BufRead,
6 | | {}
| |__^
The error message is well covered in existing questions:
Why does a generic method inside a trait require trait object to be sized?
What does "Sized is not implemented" mean?
Working with trait objects requiring sized
Why is the `Sized` bound necessary in this trait?
TL;DR: trait objects aren't guaranteed to have a size, but generics have a Sized trait bound by default.
read is getting passed by value
Yes, everything in Rust is always passed by value. Sometimes that value happens to be a reference though.
read_message is expecting a &mut BufRead
It is not. It is expecting a generic type that implements the trait BufRead. These two signatures are different:
// Reference to a concrete type
pub fn read_message<R>(read: &mut R)
where
R: BufRead,
// Trait object
pub fn read_message<R>(read: &mut BufRead)
See also:
What is the difference between <T: Trait> Box<T> and &Trait / Box<Trait>?
What makes something a "trait object"?
a &mut &mut BufRead, which is not the expected type
It's a perfectly cromulent type. BufRead is implemented for any mutable reference to any type that implements BufRead itself:
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B
Besides, in this case you don't have a &mut &mut BufRead, you have a &mut &mut R. The concrete monomorphization for the types you've shown is actually a &mut &mut Bufreader.
You can fix it by :
changing the read_message function to accept unsized types. This is fine since R is always behind a pointer:
pub fn read_message<R>(read: &mut R)
where
R: ?Sized + BufRead,
changing the parse_capnp function to take a reference to a concrete type instead of a trait object:
fn parse_capnp<R>(read: &mut R)
where
R: BufRead,
{
read_message(read);
}
changing the parse_capnp function to take a concrete type instead of a trait object. You then need to take a reference to it yourself:
fn parse_capnp<R>(mut read: R)
where
R: BufRead,
{
read_message(&mut read);
}

Why is it necessary to add redundant trait bounds even though my trait uses those same traits as bounds?

I have been trying to code a trait which requires a type to implement Add (and further down the line other operations for vector spaces) with itself as well as among its references. The following is a small example, illustrating the problem I ran into:
use std::ops::Add;
#[derive(Debug)]
struct MyVec<T>(Vec<T>);
impl<'a, 'b, T: Copy + Add> Add<&'a MyVec<T>> for &'b MyVec<T> {
type Output = MyVec<T::Output>;
fn add(self, other: &'a MyVec<T>) -> Self::Output {
/* ... */
}
}
impl<'a, T: Copy + Add> Add<MyVec<T>> for &'a MyVec<T> {
/* ... */
}
impl<'a, T: Copy + Add> Add<&'a MyVec<T>> for MyVec<T> {
/* ... */
}
impl<T: Copy + Add> Add<MyVec<T>> for MyVec<T> {
/* ... */
}
trait Addable: Add<Self, Output = Self>
where
Self: Sized,
for<'a> &'a Self: Add<Self, Output = Self>,
for<'b> Self: Add<&'b Self, Output = Self>,
for<'a, 'b> &'a Self: Add<&'b Self, Output = Self>,
{
}
impl<T: Copy + Add<Output = T>> Addable for MyVec<T> {}
fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
x + y
}
fn main() {
let v = MyVec(vec![1, 2, 3]);
let w = MyVec(vec![2, 4, 6]);
println!("{:?}", add_stuff(&v, &w));
}
I use the newtype pattern to create an alias of Vec so I can implement a foreign trait (Add) on a foreign struct (Vec).
I implement Add for MyVec and its references. The associated type Output is always the (unreferenced) MyVec. The latter three impls are implemented in terms of the first.
Addable is the central trait that I want to demo. Things that are addable should allow themselves and their references to be added with the result being Self. Particularly, in add_stuff I want the expression x + y + x to be valid where x + y gives a non-ref which can be added with x (which has not been moved out of, because it's a ref) to produce another non-ref.
I don't get any complaints from the compiler regarding the implementation of the Addable trait on MyVec. Specifically, the compiler seems to recognize that the above impls satisfy the bounds in the where clause.
However, I get the following compiler errors:
error[E0277]: the trait bound `for<'a> &'a T: std::ops::Add<T>` is not satisfied
--> src/main.rs:33:1
|
33 | / fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
34 | | x + y
35 | | }
| |_^ no implementation for `&'a T + T`
|
= help: the trait `for<'a> std::ops::Add<T>` is not implemented for `&'a T`
= help: consider adding a `where for<'a> &'a T: std::ops::Add<T>` bound
= note: required by `Addable`
error[E0277]: the trait bound `for<'a, 'b> &'a T: std::ops::Add<&'b T>` is not satisfied
--> src/main.rs:33:1
|
33 | / fn add_stuff<'a, 'b, T: Addable>(x: &'a T, y: &'b T) -> T {
34 | | x + y
35 | | }
| |_^ no implementation for `&'a T + &'b T`
|
= help: the trait `for<'a, 'b> std::ops::Add<&'b T>` is not implemented for `&'a T`
= help: consider adding a `where for<'a, 'b> &'a T: std::ops::Add<&'b T>` bound
= note: required by `Addable`
This can be fixed by amending the add_stuff function with a where clause as suggested by the compiler:
where
for<'c, 'd> &'c T: Add<&'d T, Output = T>,
for<'c> &'c T: Add<T, Output = T>,
I do not understand why this is necessary. I thought by specifying a bound in the definition of the trait I could rely on that bound being met for any type that implements that trait? Having to add these where clauses every time sort of defies the whole point of my Addable trait.
Googling brought up this GitHub issue which I don't understand fully but which might be related? That would suggest this is indeed a bug in Rust (which hasn't been fixed for a very long time).
You've hit a shortcoming of the Rust compiler as it currently is. RFC 2089 proposed to make it work as you expect, and was accepted in December 2017.
However, as of today, the feature isn't implemented. The tracking issue for the implementation hasn't seen much activity yet, so it appears implementation hasn't even started. It appears that some fundamental improvements to the compiler's trait bound handling are necessary before this particular feature can be efficiently implemented (search keyword: chalk).

Why do I get the error "the trait `Foo` is not implemented for `&mut T`" even though T implements the trait?

I have this source:
pub fn draw<G, C>(&self, font: &mut C, draw_state: &DrawState, transform: Matrix2d, g: &mut G)
where
C: CharacterCache,
G: Graphics<Texture = <C as CharacterCache>::Texture>,
{
self.properties.draw(
self.text.as_str(),
&mut font,
&draw_state,
transform,
g,
);
}
And the error
the trait bound `&mut C: graphics::character::CharacterCache` is not satisfied
(the trait `graphics::character::CharacterCache` is not implemented for `&mut C`)
The only aspect of C that is defined is that it implements CharacterCache, yet the error says the opposite.
DrawState, Matrix2d, CharacterCache and its implementations, Texture, and self.properties (Text) are provided by the Piston 2d graphics library. There must be something about traits in general that I'm misunderstanding.
The Text::draw function signature:
fn draw<C, G>(
&self,
text: &str,
cache: &mut C,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
C: CharacterCache,
G: Graphics<Texture = C::Texture>,
T, &T, and &mut T are all different types; and that means that &mut &mut T is likewise a different type. Traits are not automatically implemented for references to a type. If you wish to implement a trait for either of the references, you need to write it out explicitly.
As an example, this exhibits the same problem:
trait Foo {}
#[derive(Debug, Copy, Clone)]
struct S;
impl Foo for S {}
fn example<T>(_: T)
where
T: Foo,
{}
fn main() {
let mut s = S;
example(s);
example(&s); // the trait bound `&S: Foo` is not satisfied
example(&mut s); // the trait bound `&mut S: Foo` is not satisfied
}
Explicit implementations of the trait for the references solve the problem:
impl<'a> Foo for &'a S {}
impl<'a> Foo for &'a mut S {}
In many cases, you can delegate the function implementations to the non-reference implementation.
If this should always be true, you can make it so by applying it to all references to a type that implements a trait:
impl<'a, T> Foo for &'a T where T: Foo {}
impl<'a, T> Foo for &'a mut T where T: Foo {}
If you don't have control over the traits, you may need to specify that you take a reference to a generic type that implements the trait:
fn example<T>(_: &mut T)
where
for<'a> &'a mut T: Foo,
{}
See also:
When should I not implement a trait for references to implementors of that trait?
The error message says that "graphics::character::CharacterCache is not implemented for &mut C"; and indeed, all you have said in your where-clause is that C: CharacterCache, not &mut C: CharacterCache.
(In general, one cannot conclude &mut Type: Trait if all one knows is Type: Trait)
I'm assuming that the .draw method that you are invoking on self.properties: Text wants a &mut C for its argument, so you might be able to pass in either font or &mut *font, but I'm guessing that your extra level of indirection via &mut font is causing a problem there.
In other words:
self.properties.draw(
self.text.as_str(),
&mut font,
// ~~~~~~~~~ is not the same as `font` or `&mut *font`
&draw_state,
transform,
g,
);
Sidenote for Experienced Rustaceans:
This kind of coding "mistake" (putting in an extra level of indirection) actually occurs more than you might think when programming in Rust.
However, one often does not notice it, because the compiler will often compare the expected type with the type that was provided, and will apply so-called deref coercions to turn in the given value into an appropriate argument.
So if you consider the following code:
fn gimme_ref_to_i32(x: &i32, amt: i32) -> i32 { *x + amt }
fn gimme_mutref_to_i32(x: &mut i32, amt: i32) { *x += amt; }
let mut concrete = 0;
gimme_mutref_to_i32(&mut concrete, 1);
gimme_mutref_to_i32(&mut &mut concrete, 20);
let i1 = gimme_ref_to_i32(&concrete, 300);
let i2 = gimme_ref_to_i32(& &concrete, 4000);
println!("concrete: {} i1: {} i2: {}", concrete, i1, i2);
it will run without a problem; the compiler will automatically insert dereferences underneath the borrow, turning &mut &mut concrete into &mut *(&mut concrete), and & &concrete into & *(&concrete) (aka &mut concrete and &concrete respectively, in this case).
(You can read more about the history of Deref Coercions by reading the associated RFC.)
However, this magic does not save us when the function we are calling is expecting a reference to a type parameter, like so:
fn gimme_mutref_to_abs<T: AddAssign>(x: &mut T, amt: T) { *x += amt; }
let mut abstract_ = 0;
gimme_mutref_to_abs(&mut abstract_, 1);
gimme_mutref_to_abs(&mut &mut abstract_, 1);
// ^^^^ ^^^^^^^^^^^^^^
// compiler wants &mut T where T: AddAssign
println!("abstract: {}", abstract_);
In this code, the Rust compiler starts off assuming that the input type (&mut &mut i32) will decompose into some type &mut T that satisfies T: AddAssign.
It checks the first case that can possibly match: peel off the first &mut, and then see if the remainder (&mut i32) could possibly be the T that we are searching for.
&mut i32 does not implement AddAssign, so that attempt to solve the trait constraints fails.
Here's the crucial thing: the compiler does not then decide to try applying any coercions here (including deref coercions); it just gives up. I have not managed to find a historical record of the basis for giving up here, but my memory from conversations (and from knowledge of the compiler) is that the trait resolution step is expensive, so we choose not to try to search for potential traits on each step of a coercion. Instead, the programmer is expected to figure out an appropriate conversion expression that will turn the given type T into some intermediate type U that the compiler can accept as the expected type.

Resources