Allow deref assignments on variables without requiring mut keyword#109939
Allow deref assignments on variables without requiring mut keyword#109939b-naber wants to merge 3 commits intorust-lang:masterfrom
Conversation
|
Some changes occured in cc @BoxyUwU This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras |
This comment has been minimized.
This comment has been minimized.
5996737 to
4a2948a
Compare
|
These commits modify the If this was intentional then you can ignore this comment. |
f004b91 to
8d6cf27
Compare
This comment has been minimized.
This comment has been minimized.
8d6cf27 to
0f7d5ca
Compare
|
Hmm, I don't think this is entirely consistent. If I have a struct S(u8);
impl Deref for S {
type Target = u8;
fn deref(&self) -> &u8 {
&self.0
}
}
impl DerefMut for S {
fn deref_mut(&mut self) -> &mut u8 {
&mut self.0
}
}
fn main() {
let x = S(0);
dbg!(x.0); // 0
*x = 1_u8;
dbg!(x.0); // 1
} |
|
I think this touches on the point of what Deref(-Mut) implementations are valid. In the docs it says 'DerefMut should only be implemented for smart pointers to avoid confusion.'. Should these traits even be implemented for |
|
Yeah, for smart pointers it makes sense, but I don't think there's a non-surprising way to restrict this functionality to those |
|
Personally, I feel strongly that the 'smart pointers' wording is, at best, misleading - even the std contains deref impls for things that directly contain the provided value (such as |
|
I think this at least needs a lang fcp, but I agree with @CraftSpider's perspective above. |
|
This changes the builtin This is consistent with mutable references: the following snippet already compiles fn derefs(x: &mut u32) {
*x = 1;
}With this PR, the following now also compiles use std::cell::RefMut;
fn derefs_ref_mut(x: RefMut<'_, u32>) {
*x = 1;
}The status quo feels inconsistent to me and was quite annoying when using As stated by @JakobDegen and @CraftSpider this is however somewhat weird for things which aren't simply 'smart pointers'. There are multiple impls like this in std. This PR would therefore allow the following to compile which feels very undesirable: fn foo(x: Vec<u32>) {
x.sort()
}It feels difficult to restrict this PR to only apply to smart pointers without actually increasing the complexity/inconsistency 🤔 Given the above, I think we should not merge this PR. We may want to open an issue as the std comment "Because of this, I can't think of any convincing argument for why If so, we may want to extend this behavior to smart pointers by adding an attribute cc @rust-lang/lang @rust-lang/libs-api |
|
The fact I don't think it makes sense to be able to get a |
|
I think everything important against this PR as written has been said. We should probably move to a lang team zulip topic to discuss the mentioned alternatives and whether anything should be done here at all. I'll go ahead and close this PR. |
We currently require
yin this example to bemut:It seems somewhat inconsistent to not allow this to compile given that we "require"
DerefMutto only be implemented on smart pointers and given that we allow this:This PR would allow
DerefMut::deref_mutto be called on receivers that aren't declaredmut.r? @lcnr