Deref coercions do not work with blocks
It seems that the compiler handles a block differently when coercing a value.
fn f(_: &str) {}
fn main() {
let x = "Akemi Homura".to_owned();
f(&x); // OK
f(&(x)); // OK
f(&{x}); // Error
}
RFC 401 says that a block with type U is also a target for coercion, so I think this behavior is a bug.
blocks, if a block has type
U, then the last expression in the block (if it is not semicolon-terminated) is a coercion site toU. This includes blocks which are part of control flow statements, such asif/else, if the block has a known type.
Also, the compiler seems to be able to coerce blocks using some "trivial" rules (e.g. &mut T -> &T).
fn f(_: &i32) {}
fn main() {
let x = &mut 42;
f(x); // OK
f((x)); // OK
f({x}); // OK
}
So I guess this is more likely a problem of auto-deref.
CC @nrc
Aria Desires at 2015-07-11 23:03:42
As some users have discovered,
{x}.itemcan be used to force ax: &mut Xto move instead of reborrow. Is that related? We might not be allowed to break that.bluss at 2015-07-12 08:45:57
I suspect this is something specific to deref coercions. I think it is 'just a bug', but I don't know how easy it is to fix.
Nick Cameron at 2015-07-12 22:46:45
This blocks usage of
try!together with deref coercions if I understand this bug correctly:let _: &Path = &try!(env::current_dir());fails to compile.Tobias Bucher at 2015-08-20 11:40:24
@tbu- Yup, actually this issue was found by a Stack Overflow question that tried the same thing.
Barosl Lee at 2015-08-21 06:46:13
There is also this rust-users thread with a very similar problem.
llogiq at 2015-09-19 13:42:09
triage: I-nominated
Nick Cameron at 2015-09-21 21:18:32
triaged because it is such an annoying bug. Recommend p-medium.
Nick Cameron at 2015-09-21 21:19:09
cc @eddyb
Niko Matsakis at 2015-10-01 20:17:30
triage: P-medium
Niko Matsakis at 2015-10-01 20:18:27
It would be very helpful to point out the error, which is:
<anon>:8:9: 8:10 error: mismatched types: expected `str`, found `collections::string::String` (expected str, found struct `collections::string::String`) [E0308] <anon>:8 f(&{x}); // Error ^So the problem could be that
strpropagated through the block tox, despite being unsized. As blocks are always rvalues, maybe the "expected type" propagation doesn't deal with unsized values being mere hints in the block case?Eduard-Mihai Burtescu at 2015-10-03 17:28:02
Update: That was dumb of me: I did not realize this only ever happens with
str. Of course it does, because I never implemented it.Eduard-Mihai Burtescu at 2016-02-14 13:23:16
This issue should be reopened:
fn f(_: &i32) {} fn main() { let x = Box::new(1i32); f(&x); // OK f(&(x)); // OK f(&{x}); // Error }Donough Liu at 2021-04-04 14:41:13
I should've renamed the title of this issue, I believe (based on my comments in this thread) that this issue was specifically about
strnot working the same was[T].I doubt your example ever worked, because the block gets
i32as the expected type and that isSized, so there's no way to rule it out as the type of the block.Eduard-Mihai Burtescu at 2021-04-30 11:33:00