You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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...
The text was updated successfully, but these errors were encountered:
…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
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.:
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 theBar
structure. This is always legal (since there's only oneBar
member).Writing
foo.member
will access a member explicitly declared inFoo
, 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 theBar
field. This is always legal (since there's only oneBar
member).Writing
foo.method(...)
works similarly to accessing a member - if there's a method explicitly declared forFoo
, 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.*
orfunction(self)
accesses are interpreted using the type of the anonymous field. For example, ifFoo
provides afoo
method, andBar
also provides afoo
method, andBar.bar
invokesself.foo
, thenFoo.bar
will invokeBar.foo
, notFoo.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, ifBar
implements a trait, one should typically simply sayimpl 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 ofBar
.Diamonds
Design choice D: If both
Bar
andBaz
have an anonymous field calledQux
, then there are two separate instances ofQux
-foo.Bar.Qux...
andfoo.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. Possiblydelegate * 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...
The text was updated successfully, but these errors were encountered: