-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ref/& Destructuring Inconsistency in Structs #2819
Comments
Capturing and destructuring are two different concepts. struct Foo {
x: Option<u32>
}
fn main() {
let f = Foo { x: Some(123) };
if let Foo { x: Some(ref inner) } = f {
println!("{}", inner);
}
} Why would it be any different for references? |
@phaazon I think you're misunderstanding their request. They are aware that What they are asking for is that the field short-hand syntax should be extended to support references. Right now you can use the field short-hand syntax, such as But that short-hand syntax does not work with references, so you cannot use |
Ah, yeah, then I’m still against it. 😄 If that gets accepted, in five months from now, someone will complain they can’t do |
Thank you for the clarification @Pauan -- apologies if my initial title was unclear/ambiguous. Perhaps I'm unclear on the official naming convention, but as I understand it, the following example: struct Test {
a: i32
}
fn main() {
let test = Test {
a: 1234,
};
let Test {ref a} = test; //a is of type &i32 here.
} Is an example of de-structuring the Test struct, and assigning the local variable Currently, this short-hand syntax supports borrowing, but not de-referencing. To me, this seems unintuitive: almost everywhere else that a I understand why this may confuse newcomers into believing this would work for an |
@quixotrykd Actually, you can already use let a = 5;
if let Some(ref b) = Some(a) {}
if let Some(&b) = Some(&a) {}
let ref b = Some(a);
let &b = &Some(a); Using |
You are right about the fact that
let Derefed {&val} = a; // error: expected identifier, found `&` Here, struct Foo {
a: Option<u32>
}
let Foo { Some(a) } = this_doe_not_make_sense; Again, accepting |
@phaazon Nobody is suggesting As for the inconsistency, I think you are misunderstanding something. Foo { bar: <pattern> }
Foo { bar } // equivalent to Foo { bar: bar }
Foo { ref bar } // equivalent to Foo { bar: ref bar }
Foo { mut bar } // equivalent to Foo { bar: mut bar }
Foo { ref mut bar } // equivalent to Foo { bar: ref mut bar }
Foo { .. } // ignores the fields As you can see, structs do not use patterns, they have their own special struct-only syntax. Notice that you can use So since we already have an exception for And there is no risk of the slippery slope of "what if people ask to add in more exceptions later?" because there aren't any more exceptions: none of the other patterns make sense in field position, so |
My point was: if you add |
@phaazon As I explained, we already have And I have found situations where |
I disagree with this perspective and agree with @phaazon. If you look at the pattern grammar (and indeed the implementation), you will find that we have: pat ::=
| "&" "mut"? pat
| "ref"? "mut"? ident
| other_stuff_in_pat
; As you can see, the non-terminal in the case of |
@Centril That is true, but I personally don't view that as being a problem or an inconsistency, because field patterns are already a subset of patterns, so there's no issue with having Or to put it another way, So I find the objection of "it only allows a subset of patterns" to be weak, since that's already true today. |
The desirable property in the record short-hand is that it reuses the grammar from |
I agree, I see no problem with having The only issue is making it recursive, so that
To be clear, I am looking at the consistency from the perspective of the user, not the grammar or the implementation. So I view it as both ergonomic and consistent (or at least, not inconsistent, just a restricted subset). But yes, I do think it is an ergonomic improvement, that would have benefited some of my programs in the past. |
There cannot be an inconsistency because the short-hand syntax doesn’t exist for items but
I think I apply, as you do, as a Rust user, and I truly and honestly don’t agree with you that Rust is inconsistent regarding the short-hand syntax and that authorizing a syntax that is either a short-hand syntax or a destructuring syntax (i.e. |
No, I have never confused those. In my previous post I even argued specifically that struct field patterns are special and different from regular patterns.
But that's also true with
Then are you against
That same argument can be used for
That is also true for
I don't really understand what you're saying. That seems like a red herring. The suggestion is to have That's completely separate from whether the Let me explain my position very clearly. Right now you can use Foo { ref foo } This is not a pattern, it is special syntax only for struct fields. It desugars to So this proposal is simply to add in It's as simple as adding a new case to the Let's look at the arguments for why we should not add in
All of the arguments against So you will need to make an argument for why |
Regarding your reply:
Everybody got what the suggestion is about. And I didn’t say that struct Foo {
bar: *const u32
}
let Foo { *bar } = foo(); That would desugar to let Foo { bar: *bar } = foo(); |
Given that we can't destructure any pointer except for references right now, I don't see that happening. |
|
@spunit262 That's also true for A new feature for using non-Copy types might be useful, but it's separate from this feature request (which is solely about syntax sugar for an already existing feature, it's not a new feature). And any solution for non-Copy types should of course apply equally to both general patterns and struct patterns. |
No it's not,
The point is I don't see much use for this, and the bit I do see, is better served by something else. |
@spunit262 Using
That's fair, but obviously some people (such as the original poster) disagree. And this syntax sugar does not prohibit other new features from being added (such as improvements for non-Copy types). |
Imagine this: let &x = foo_that_returns_a_ref(); All the concepts behind this line are the same as the ones for this: let Some(ref x) = foo_that_returns_an_option(); It’s plain pattern-matching. However, the let Foo { ref x } = foo(); Is still destructuring a let Foo { &x } = foo(); Would imply destructuring both Why we keep coming to I can clearly feel that you would like to have that feature to save some characters to type (i.e. I think the syntax to destructure a field should stay |
That is incorrect.
As I have explained many times, There is no new feature, and there is no magic, only syntax sugar for an already existing feature, just the same as how
I'm not sure where you got that idea. In both cases The only difference is that in the case of Your argument is the same as saying that
That's a good point,
Your argument also applies to
I have clearly given arguments against all of your claims of inconsistency. You have failed to provide a single argument for why Until you actually present an argument for why |
It is not. You’re still “outside” of the field. A field has a name and a value.
Up to you, but you are the one wanting to make a change, not me. You should stop focusing on syntax and care more about semantics. It’s not because |
Rust pattern matching and destructuring allows the use of
&
andref
.In the example below, the use of these is intuitive.
In this case, we end up with
ref_a
of type&u32
, andderef_b
of typeu32
. Simple enough -- we can go both ways with bothref
and&
in pattern matching.In the instance with structs, this consistency breaks down when matching struct field names. In the example that follows, this is shown:
In this case, val is borrowed as
&u32
, mirroring tuple functionality. The following example on the other hand, does not work.While not functionality-breaking, it is extremely non-intuitive that this matching only works via
ref
and not via&
for structs, when binding directly to the same variable name.The text was updated successfully, but these errors were encountered: