-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Allow inheritance between structs. #12562
Conversation
@@ -758,6 +758,13 @@ pub fn print_struct(s: &mut State, | |||
span: codemap::Span) -> io::IoResult<()> { | |||
try!(print_ident(s, ident)); | |||
try!(print_generics(s, generics)); | |||
match struct_def.super_struct { | |||
Some(t) => { | |||
try!(word(&mut s.s, " : ")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of traits, it was decided that trait X: Y { }
was to be preferred over trait X : Y { }
. I believe that this should use ": "
rather than " : "
for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Comparing with how it's implemented for trait, putting the space in the string is probably not the optimal thing to do anyway. word_space(&mut s.s, ":")
is probably better, though I haven't traced through the code to see what that actually does.)
Will syntax like |
I can't see any tests for struct A: B { ... }
fn foo(_: &B) {}
fn bar(a: &A) { foo(a) } does this patch support that yet? |
@jdm It does not - we still require all the fields in any |
@huonw No, I explicitly avoided adding any subtyping or coercions here. I think we need to think a little more about the implications of that, but I foresee adding it in another PR. |
Should sub-structs have access to private fields in parent super structs? It seems the answer is "yes" from this implementation, but it may be worth considering this and testing it one way or another. I would mildly expect the answer to be no. |
I kind of wonder if a syntax where you specify a field as "use foo: S" where the "use" keyword is syntax sugar that imports the fields in the struct namespace would be a better design, since that would give access to the base struct for free without having to introduce a "super" keyword, would allow "multiple inheritance" (this could be extended to allow importing single fields via use), and would be a simpler change to the language. Trait inheriting structs can then be an orthogonal feature, where the first field of the struct is considered as being the "parent" structure, regardless of whether it was imported or not via "use" (but with the restriction that only parents that are public are considered parents if the trait impl is in another crate, so that changing the first field of a struct is not an API change when the field is private). |
@bill-myers super is already a keyword for relative imports; |
I'd like to review |
@nikomatsakis I was going to address the comments others have made here (in particular, adding debug-info and privacy checks). You might want to hold off till then for a proper review. In the mean time, any comments on the general idea would be appreciated. |
On Wed, Feb 26, 2014 at 02:08:50PM -0800, Nick Cameron wrote:
Will do. |
Is this design written up somewhere? |
@brson it is the first part of http://smallcultfollowing.com/babysteps/blog/2013/10/24/single-inheritance/ |
@nikomatsakis - ready for review I'm not sure how much in the way of tests are required for debug-info - I added a simple test, let me know if we need more. |
a possible point in favour of having single inheritance: fewer symbols to remember when accessing struct members, which is a bigger deal without code-completion. "which sub-member contains which named field?" .. "i want .name' .. if a primitive tool just lists all struct members after pressing '.' , a codebase that has single-inheritance will have a smaller amount of false posatives in that list |
One more idea,
Even if you dont want that, it would be nice to make an error message that does that lookup for you... "Bar has no member id... did you mean .foo.id" Without this I'm going probably going to end up making a trait of accessors. trait IFoo { fn id()->int..} impl IFoo for Bar ... I thought that traits inheriting structs would also let you use struct elements in default implementations, which would also be really helpful. This is about ease of navigating code, ease of refactoring.. if you start moving fields between structures.. (which should be part of the common base ? .. you evolve that decision over time as your source grows..) .. you have less to go back and rewrite. |
Sorry the commits are kind of messy - lots of rebasing going on. |
@nikomatsakis r? I rebased everything and added a requirement for the virtual keyword. Its all feature gated, so if we do something different for the DOM problem it shouldn't be too hard to rip out. But if we do go the virtual structs route, then this is the first step and it will rot quickly if we don't land it, I think. |
@nick29581 ok, I read through it. Everything looks fairly reasonable. I think the big comment is that I'd rather see the set of struct fields collected in a pre-pass or sidetable rather than scraping and re-scraping them from the AST. If you fear bitrot, would you prefer to land and then address that? |
Thanks for the review. I can make the changes now. I was worried about bit rot if we leave this until we are ready to implement virtual structs or post-1.0, another few days won't hurt. |
@nick29581 ping me when updated |
@nikomatsakis pushed an updated version. It doesn't quite use a side table for all the fields of a struct. I did move some of the field checking and collation into the collect phase and I build side tables for the super-struct of a struct and the declared fields of a struct. (I couldn't create a table for all fields here because some of the super-structs may not yet have been encountered, of course we could do another pass, but more on that later). So after collect, we never scrape the AST, but we don't have a simple mapping from a struct to all its fields. I add a few methods to ty for getting all the fields for a struct (in ast and ty flavours, annoyingly), so this is only done in one place, eliminating the errors you worried about. If you like, we could cache these lists of all fields here. I believe that is easier than doing this pre-emptively either as a new pass or part of an existing one. I haven't done it because I'm not convinced it is a worthwhile optimisation for now, but I don't have a philosophical objection if you think otherwise. |
@nikomatsakis updated and ready for re-review |
SIgh, needs a rebase |
Rebased. @nikomatsakis (or anyone else) please could you re-r+? |
Oh ffs, needs another rebase - looks like I was right about this bit-rotting quickly... |
Rebased again. Please could someone r+? |
AGAIN?! :-( |
OK, let's try again. Can someone r+ please? |
OK, I am mystified by that failure - it seems to be because of a missing feature gate, but the required |
Oh, wait, did it merge anyway? I am confused. |
This is still open, so nope. The problem is the check-fast driver; it creates a single huge crate from all the tests that don't have |
(If #13288 lands this cycle, then this just needs a retry, the check-fast driver won't exist and so |
Could this get a retry and/or another r+ please? |
Oh, someone changed an error message. That is a dumb way to fail tests. Sigh. Rebased/updated again, please to r+? |
No subtyping, no interaction with traits. Partially addresses rust-lang#9912.
Rebased and fixed the failing test. Could someone r+ again please? |
No subtyping, no interaction with traits. Partially addresses #9912.
Wow this landed! |
Split completion context module into definitions and analysis parts
Allow `filter_map_identity` when the closure is typed This extends the `filter_map_identity` lint to support typed closures. For untyped closures, we know that the program compiles, and therefore we can safely suggest using flatten. For typed closures, they may participate in type resolution. In this case we use `Applicability::MaybeIncorrect`. Details: https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/Should.20.60filter_map_identity.60.20lint.20when.20closures.20are.20typed.3F changelog: `filter_map_identity` will now suggest using flatten for typed closures. r? `@y21` && `@Centri3`
No subtyping, no interaction with traits. Partially addresses #9912.