> So, I have a package 'ifhack' that exports a type 'Hack'. That type
> has an unexported field 'private'. There is an exported String method
> bound to the Hack type.
>
> Now, as I expected I have a hard type actually calling the String()
> method as it's receiver is by-value, not by-reference, and calling
> by-value requires an implicit copy, and you can't copy a value that
> has an unexported field.
>
> What is strange however is that if I indirect via a variable with an
> interface type (e.g: variable 's' with type fmt.Stringer), I am then
> able to call the String() function.
>
> So, this behaviour raises a number of questino which I'm hoping
> someone
> can help answer.
>
> 1: Is this expected behaviour?
>
> 2: If this is expected behaviour, why?
>
> 3: Is there anyway to legitimately call an exported method with a by-
> value
> receiver, when the receiver type has unexported fields?
>
> 4: If not, is there any reason why the compiler/type-checker should
> allow
> this construct in the first place?
This does seem strange. Please open an issue for this.
At the moment it's not completely clear to me what is correct here. It
seems reasonable that if code can not call a method that it should not
be permitted to assign the object to an interface which uses that
method. That is a little odd, though, because it would mean that an
assignment to an interface type would succeed in the package where the
type is defined but would not succeed in a different package.
Annoyingly, 6g and gccgo behave differently here, and arguably neither
is correct.
Thanks for noticing this.
Ian
I would guess that the proper fix is actually in the opposite
direction. The package a type is defined in is always allowed to copy
values even when they include private fields. The only place one can
define a method on a type is its own package, so that kind of copy
should also be considered internal to the package and thus acceptable.
If the package author doesn't want external use of such a copy then
either a) do not export the type, or b) do not export the method, or
c) use a reference receiver for the method.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter
> Would disabling the creation of these methods in the first place be a
> way of solving this problem (as suggested in #3 or #4?)
>
> As far as I can tell, if copying struct with private fields is
> considered 'bad', then there is no real reason for exported methods.
> (As they can't ever be used externally).
I would guess that the proper fix is actually in the opposite
direction. The package a type is defined in is always allowed to copy
values even when they include private fields. The only place one can
define a method on a type is its own package, so that kind of copy
should also be considered internal to the package and thus acceptable.
If the package author doesn't want external use of such a copy then
either a) do not export the type, or b) do not export the method, or
c) use a reference receiver for the method.