Skip to content

Proposal: Anonymous fields #9728

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

Closed
orenbenkiki opened this issue Oct 5, 2013 · 2 comments
Closed

Proposal: Anonymous fields #9728

orenbenkiki opened this issue Oct 5, 2013 · 2 comments

Comments

@orenbenkiki
Copy link

This is an attempt at defining possible implementation of anonymous fields (inspired by Go). There are some "obvious" design choices and some not-so-obvious ones involved. The following is what I hope to be a "reasonable" combination. Here goes...

The idea is to allow fields without a name, e.g.:

struct Foo {
    Bar, // Anonymous field
    Baz, // Another anonymous field
    named: int // Named field
}

It is illegal to have two anonymous fields with the same type (as that would be ambiguous).

Members

Writing foo.Bar.member would access members of the Bar structure. This is always legal (since there's only one Bar member).

Writing foo.member will access a member explicitly declared in Foo, if there is one. Otherwise, of there's only one anonymous member providing the member, it is accessed. Otherwise (if there's no such anonymous field, or if there's more than one), it is an error.

Methods

Writing foo.Bar.method(...) would invoke the method on the Bar field. This is always legal (since there's only one Bar member).

Writing foo.method(...) works similarly to accessing a member - if there's a method explicitly declared for Foo, it is called; if there's only one anonymous field providing it, it is called; otherwise, it is an error.

Design choice A: When a method of an anonymous field is invoked, all self.* or function(self) accesses are interpreted using the type of the anonymous field. For example, if Foo provides a foo method, and Bar also provides a foo method, and Bar.bar invokes self.foo, then Foo.bar will invoke Bar.foo, not Foo.foo.

Traits

Design choice B: There are no implicit traits for Foo.

When implementing a trait for Foo, it is allowed to omit the implementation of a function if it is unambiguously available by any anonymous field. So, if Bar implements a trait, one should typically simply say impl Trait for Foo {} and be done.

However, if an explicit function is defined inside the impl Trait for Foo { ... } block, it would be used instead of any anonymous field function. This is consistent with the function calling semantics above. For example, it may be required to specify a function if it is provided by more than one anonymous field.

Access

Design choice C: Public/private control of members and methods accessed via the anonymous field is inherited from the type of the anonymous field. That is, Foo gets no special access rights to the internals of Bar.

Diamonds

Design choice D: If both Bar and Baz have an anonymous field called Qux, then there are two separate instances of Qux - foo.Bar.Qux... and foo.Baz.Qux.... This is consistent with reusing the compiled version of anonymous field functions, and avoids the nastiness involved with the diamond multiple-inheritance pattern. So, no equivalent to C++'s "virtual inheritance".

Alternatives

An alternative to anonymous fields is to provide a delegate syntax, allowing delegating certain methods to (named) fields. Delegation would also need to work for members. The syntax for delegation would be tricky as we don't want to repeat the whole list of methods/members on the one hand, but would need to provide some control on the other hand. Possibly delegate * to field_name would be enough, but that is essentially the same having anonymous fields.

Other issues?

The above design choices are made with an eye for a useful simple semantics combined with a simple vtable-based implementation. This doesn't make them "right" and I probably missed some issues...

@orenbenkiki
Copy link
Author

@thestinger
Copy link
Contributor

I think this needs to be done through the new RFC process: https://github.com/rust-lang/rfcs/pulls

It hasn't gotten any attention here, and there are currently several alternatives proposed there.

flip1995 pushed a commit to flip1995/rust that referenced this issue Nov 21, 2022
…1995

move `UNINLINED_FORMAT_ARGS` to pedantic

As discussed in zulip, we are moving this lint to pedantic to be backported

changelog: [`UNINLINED_FORMAT_ARGS`]: move to pedantic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants