Uh oh!
There was an error while loading. Please reload this page.
Support Self in struct expressions and patterns - #37035
Conversation
eddyb
left a comment
There was a problem hiding this comment.
LGTM, certainly something I'd like to use myself.
cc @rust-lang/lang Any objections?
There was a problem hiding this comment.
Don't we have something like this already?
There was a problem hiding this comment.
I'm not entirely sure, I've searched a bit, but found only type pretty printing (in the same ppaux.rs), but no short descriptions.
There was a problem hiding this comment.
That's because it's hidden away in some error reporting logic.
There was a problem hiding this comment.
Oops, this is no longer necessary, need to remove.
There was a problem hiding this comment.
Due to the "actual variant definition" vs "variant constructor" split?
There was a problem hiding this comment.
No, due to tcx.parent_def_id(did) a few lines above.
Only type arguments are taken from the variant (from base_segments.last()), ast_path_to_ty works with the enum after that and returns enum's type, which cannot be a function.
Can we have a test to make sure this fails? I'd write it myself but not sure how. structFoo<A>{inner:A};traitBar{fnbar();}implBarforFoo<i32>{fnbar(){Self{inner:1.5f32};}} |
petrochenkov
commented
Oct 8, 2016
@Ericson2314 |
Ericson2314
commented
Oct 8, 2016
Thanks! |
nrc
commented
Oct 8, 2016
This feels a little weird to me since |
I've heard something about this being true before 1.0, but now paths in struct expressions/patterns are types, possibly with provided type arguments, not just type constructors. structS<T,U = u16>{a:T,b:U,}typeAlias<T> = S<T>;fnmain(){// Everything below is legallet s = S::<u8,u8>{a:0,b:1};// desugared into S::<u8, u8> { a: 0, b: 1 };let s = S::<u8>{a:0,b:1};// desugared into S::<u8, u16> { a: 0, b: 1 };let s = S{a:0,b:1};// desugared into S::<_, _> { a: 0, b: 1 };let s = Alias::<u16>{a:0,b:1};// desugared into S::<u16, u16> { a: 0, b: 1 };}So, |
nrc
commented
Oct 9, 2016
@petrochenkov huh, ok, then I feel much better about this, thanks for the explanation! Does this mean that if the type params or lifetime params of the values for fields disagree with the params of |
petrochenkov
commented
Oct 9, 2016
@Ericson2314 asked for the same test a few messages above and I added compile-fail/struct-path-self-type-mismatch.rs |
Ericson2314
commented
Oct 10, 2016
@nrc not knowing that feature prior to this also led me to think of the test case. :) |
nrc
commented
Oct 11, 2016
@petrochenkov sweet, thanks! |
aturon
commented
Oct 11, 2016
What about the common case of constructors with generics? structFoo<T>{ ... }impl<T>Foo<T>{fnnew<U>(u:U) -> Foo<U>{Self{ ...}// is this Foo<T> or Foo<U>?}} |
aturon
commented
Oct 11, 2016
durka
commented
Oct 11, 2016
@aturon I think you might need a About [root@li1424-173 rust]# build/x86_64-unknown-linux-gnu/stage1/bin/rustc - <<<"structFoo<T>{inner:T}impl<T>Foo<T>{fnnew<U>(u:U) -> Foo<U>{Self{inner: u }}}fnmain(){}" │··
error[E0308]: mismatched types │··
--> <anon>:1:87 │··
| │··
1 | struct Foo<T> { inner:T} impl<T> Foo<T> {fnnew<U>(u:U) -> Foo<U>{Self{inner: u }}}fnmain(){} │··
| ^ expected type parameter, found a different type parameter │··
| │··
= note: expected type `T` │··
= note: found type `U` │··
│··
error[E0308]: mismatched types │··
--> <anon>:1:73 │··
| │··
1 | struct Foo<T> { inner:T} impl<T> Foo<T> {fnnew<U>(u:U) -> Foo<U>{Self{inner: u }}}fnmain(){} │··
| ^^^^^^^^^^^^^^^^^ expected type parameter, found a different type parameter │··
| │··
= note: expected type `Foo<U>` │··
= note: found type `Foo<T>` │··
│··
error: aborting due to 2 previous errors@petrochenkov can we get this to work for tuple structs as well? [root@li1424-173 rust]# build/x86_64-unknown-linux-gnu/stage1/bin/rustc - <<<"structFoo<T>(T);impl<T>Foo<T>{fnnew<U>(u:U) -> Foo<U>{Self(u)}}fnmain(){}" │··
error[E0425]: unresolved name `Self` │··
--> <anon>:1:64 │··
| │··
1 | struct Foo<T>(T);impl<T>Foo<T>{fnnew<U>(u:U) -> Foo<U>{Self(u)}}fnmain(){} │··
| ^^^^ unresolved name │··
│··
error:aborting due to previous errorNote that |
aturon
commented
Oct 11, 2016
Let's try that again, with a team: @rfcbot fcp merge |
eddyb
commented
Oct 11, 2016
@durka Type aliases also don't work for tuple structs - but you can have a function with the same name. |
durka
commented
Oct 11, 2016
Oh, I didn't know that type aliases don't work for tuple structs. And you don't even get a warning, just an error when you try to use the alias. That's super weird, but yeah orthogonal to this PR. |
FCP proposed with disposition to merge. Review requested from: No concerns currently listed. |
aturon
commented
Oct 11, 2016
I feel like I've run into cases like this from time to time, though probably in all cases it suffices to make a separate In any case, I think the proposed behavior for this PR is fine there. |
nrc
commented
Oct 11, 2016
AIUI, this is a case of the case I was asking about and your example should give a type error since |
petrochenkov
commented
Oct 11, 2016
Added this example #37035 (comment) to the tests. |
rfcbot
commented
Oct 13, 2016
All relevant subteam members have reviewed. No concerns remain. |
rfcbot
commented
Oct 20, 2016
It has been one week since all blocks to the FCP were resolved. |
nikomatsakis
commented
Oct 21, 2016
OK, seems like we're all on board with letting this change go forward. |
bors
commented
Oct 27, 2016
☔ The latest upstream changes (presumably #36695) made this pull request unmergeable. Please resolve the merge conflicts. |
Diagnostics for struct path resolution errors in resolve and typeck are unified. Self type is treated as a type alias in few places (not reachable yet). Unsafe cell is seen in constants even through type aliases. All checks for struct paths in typeck work on type level.
petrochenkov
commented
Oct 27, 2016
@bors r=eddyb |
bors
commented
Oct 27, 2016
📌 Commit 8a38928 has been approved by |
bors
commented
Oct 28, 2016
Support `Self` in struct expressions and patterns
Struct expressions and patterns generally support type aliases `Alias { field: 10 }` i.e. they already have to work with `ty::Ty` to do their job. `Self` is a type alias (when it's not a type parameter) => struct expressions and patterns should support `Self`.
Typical example:
```
impl MyStruct {
fn new() -> Self {
Self { a: 10, b: "Hello" }
}
}
```
The first commit does some preparations and cleanups, see the commit message for details.
This also fixes couple of bugs related to aliases in struct paths (fixes#36286).
EDIT:
Since struct expressions and patterns always work with `ty::Ty` now, associated paths in them are also supported. If associated type `A::B` successfully resolves to a struct (or union) type, then `A::B { /* fields */ }` is a valid expression/pattern. This will become more important when enum variants are treated as [associated items](#26264 (comment)).
r? @eddybbors
commented
Oct 28, 2016
nikomatsakis
commented
Nov 2, 2016
Discussing in the @rust-lang/core team meeting, we realized that this probably ought to have been feature-gated! |
nikomatsakis
commented
Nov 2, 2016
Even though it's small, it seems like feature-gating (and moving to stabilize in next cycle) would be more proper. |
aturon
commented
Nov 3, 2016
👍 for feature-gating. |
Feature gate Self and associated types in struct expressions and patterns cc rust-lang#37544Fixesrust-lang#37035 (comment) r? @nikomatsakis
Struct expressions and patterns generally support type aliases
Alias { field: 10 }i.e. they already have to work withty::Tyto do their job.Selfis a type alias (when it's not a type parameter) => struct expressions and patterns should supportSelf.Typical example:
The first commit does some preparations and cleanups, see the commit message for details.
This also fixes couple of bugs related to aliases in struct paths (fixes#36286).
EDIT:
Since struct expressions and patterns always work with
ty::Tynow, associated paths in them are also supported. If associated typeA::Bsuccessfully resolves to a struct (or union) type, thenA::B { /* fields */ }is a valid expression/pattern. This will become more important when enum variants are treated as associated items.r? @eddyb