On Wed, Oct 25, 2017 at 7:10 AM, Harald Fuchs <hari.fu...@gmail.com> wrote:
> Ian Lance Taylor <i...@golang.org> writes:
>
>> On Wed, Oct 25, 2017 at 1:43 AM, Harald Fuchs
>> <hari.fu...@gmail.com> wrote:
>>>
>>> I got bitten by what I'd say is a misfeature in Go:
>>>
>>>   type T1 struct {
>>>     T2
>>>     T3
>>>   }
>>>
>>>   type T2 struct {
>>>     T4
>>>   }
>>>
>>>   type T3 struct {
>>>     foo int
>>>   }
>>>
>>>   type T4 struct {
>>>     foo int
>>>   }
>>>
>>>   func main() {
>>>     t1 := T1{
>>>       T2{
>>>         T4{
>>>           1,
>>>         },
>>>       },
>>>       T3{
>>>         2,
>>>       },
>>>     }
>>>     fmt.Printf("foo=%d\n", t1.foo)
>>>   }
>>>
>>> This prints "foo=2" which surprised me because I was unaware that T1
>>> had got another foo via T3 (with less composition depth).
>>>
>>> If I put T4 directly into T1, Go would detect the ambiguity of t1.foo
>>> (because the composition depth is the same).
>>
>> What is the misfeature, though?  You gave us a clear explanation of
>> what you did and what happened; thanks very  much for doing that.  But
>> you didn't say what you expected to happen instead.
>>
>> I'll speculate that perhaps you would prefer a compilation error due
>> to an ambiguous field.
>
> Yes, that's what I would have expected (sorry for not mentioning it).
>
>> Not doing that was an explicit decision.
>> Consider a struct in package P1 that embeds two structs, one from
>> package P2 and one from P3.  Suppose the struct in P3 embeds another
>> struct from P4.  Suppose that all four packages are in different
>> github repos maintained by different people; recall that one of the
>> explicit goals of the Go language is to support programming at scale.
>> With this organization, package P1 can refer directly to fields
>> defined in P2 and P3.  We want it to be possible for P4 to add a
>> field, a field that might happen to duplicate a field in P2--in this
>> example, P2 and P4 might not even know about each other at all--and we
>> want that to happen without breaking P1.  Hope that makes sense.
>
> For us, it *did* break P1 in the sense that this silently changing its
> semantics.  And how about the following?
>
>   type P1 struct {
>     P2
>     P3
>   }
>
>   type P2 struct {
>     P4
>   }
>
>   type P3 struct {
>     P5
>   }
>
>   type P4 struct {
>     foo int
>   }
>
>   type P5 struct {
>     // foo int
>   }
>
> P2 and P3 don't know each other.  P1 breaks if P5 gets another foo.
> It's almost the same (except composition depth), isn't it?

Yes.  You are only safe from changes deeper in the type hierarchy if
you only reference fields defined without embedding in the types that
you embed directly.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to