-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: Go 2: interfaces with methods which return interface{} should be fulfilled with any return type #47295
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
Comments
I don't understand how this can be implemented. Suppose |
I'm not sure of the problem. Can you elaborate @ianlancetaylor? Ideally, it would be the same code in the compiler that handles
|
In that code the compiler can see clearly that it needs to convert a string to package a
type I interface { M() interface{} } package b
type S struct {}
func (S) M() string { return "M" } package c
import "b"
func F() interface{} { return b.S{} } package d
import (
"a"
"c"
)
func F() {
s := c.F()
// Now s is type interface{}, with dynamic type b.S.
// Note that this package knows nothing about b.
// Now we are going to convert the b.S value to a.I.
// Under this proposal this conversion should work
// since b.S has method "M() string"
// and a.I has method "M() interface{}".
x := s.(a.I)
// Now x is a value with a method "M() interface{}".
// But s is a value with a method "M() string".
// How do we change "M() string" to "M interface{}"?
// That requires new code; where does that code live?
// What creates it? The compiler never sees that any
// conversion from "string" to "interface{}" is required,
// because it doesn't know the dynamic type of s.
} |
I'm not sure, if you run that code, you should get as attempting to assign a value to a type is not permitted in GoLang. |
Are you sure you copied the code directly? There is no attempt to use But you're right, I wrote d.go incorrectly, because it is missing a type assertion. I've updated the comment above. The program then compiles. When I run it with today's compiler, I get
This proposal suggests that the conversion should succeed at run time. I'm asking how that can be implemented. |
@ianlancetaylor Are you asking how to mark it as implementing the interface at compile time? what happens at run-time is irrelevant, that is, unless you can dynamically use reflect to change methods on a type such that they match an interface, and even then, keeping the current handling of the edge cases is OK. |
For complete clarity, here is the multi-package example on the Go playground: https://play.golang.org/p/TkAA0qzYMAp |
What happens at run time is not irrelevant. This proposal is saying that the conversion from the type Do you agree that if we adopt this proposal then the program above should succeed at run time? If we agree on that, then we need to understand how to implement it. And I do not understand how to do that. |
If there is a run-time check to see if s implements I, then it's easier than explicitly checking all return values. just check that the number of parameters is the same, and that the non interface{} types satisfy the current criterion |
I agree that it is possible at run time to verify that the conversion can succeed. But that is not enough. We need an actual implementation of |
@ianlancetaylor is there any type in go for which |
No. All types implement the empty interface, by definition.
I'm sorry, I don't understand. |
well if x == x.(interface{}), then there is no problem... |
It is true that But the only way that I can see that that might help is if we always compile every single method to return |
only the ones that could satisfy interfaces as imported in the code... |
@Bjohnson131 With Ian's example above, when compiling package So the only way for the compiler to safely compile package *: Note that Go uses separate compilation for each package, not a single global compilation for a whole program. At the time that the compiler is compiling package |
It seems to me that this needs to wait for generics to land, at the very least - the two are very related and generics has been in the works for years. |
True... It seems that Generics is a bigger solution to the problem at hand. |
So this would imply that two unreltaed packages can satisfy eachother's interfaces currently without importing them. IIRC this is what the go.mod is for, I've never seen an interface be satisfied from a package that's not in go.mod (or any subsequent go.mod(s)).. Is this not the case? |
Yes, two unrelated packages can satisfy each other's interfaces without either importing the other. This is separate from go.mod. It's just how the language works. A type with a |
Based on discussion above this is a likely decline. Leaving open for four weeks for final comments. |
Late to the party. Due to not having generics and a limited set of methods available I'm often doing things like
just for converting any type to interface.
One way to do this in the compiler (without compiling everything to return interface) would be to create that stub function at compile time. If that is a worth case of compile change is another question. My example above could definitely be rewritten with generics. |
But one cannot invoke the Interfacing properties of said structs without at some level importing both packages... I think you're confusing the implementation of type checking with the implementation of interfaces in general... Unless I'm confused, there's no problem that you have presented that isn't already solved by the current compiler, with the exception of the problem of checking interface return types for any other return type, and this is a change that would likely be a low-complexity add. |
@Bjohnson131 I think its possible you may be confusing the go tool, and the compiler. The compiler runs once per package, not once per program. For instance, if I have a program where Consider a program where The two unrelated packages we are talking about here could be |
No change in consensus. |
Would you consider yourself a novice, intermediate, or experienced Go programmer?
Novice-Intermediate
What other languages do you have experience with?
I don't keep a running list. If I were to name my top 3, C++ VHDL, Java
Would this change make Go easier or harder to learn, and why?
Easier, it would allow users to write interfaces which form contracts with the compiler, while keeping the flexibility of interface{}
Has this idea, or one like it, been proposed before?
Yes, though the similarity is superficial.
If so, how does this proposal differ?
The other proposals are about interface{} as a data type, this is about interface as used in a signature
Who does this proposal help, and why?
It helps those who want to abstract their code, while maintaining rigidity where needed. See also the response to question 3.
Is this change backward compatible?
Yes
What is the cost of this proposal? (Every language change has a cost).
The time of implementation, and the time of the users to learn the feature. Maybe some angry programmers who disagree with the change.
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
govet, and some parts of lint, as well as the compiler.
What is the compile time cost?
<0 ms. Compilation would be faster.
What is the run time cost?
There is 0 runtime cost. This is an idiomatic change.
Can you describe a possible implementation?
yes.
Do you have a prototype? (This is not required.)
no
Orthogonality: how does this change interact or overlap with existing features?
It would allow users to define more rigid funcs that satisfy extremely abstract interfaces.
Is the goal of this change a performance improvement?
no.
Does this affect error handling?
only in the compiler.
Is this about generics?
only if interface{} is a generic.
What is the proposed change?
interfaces with methods which take or return interface{} should be fulfilled with any return type
Please describe as precisely as possible the change to the language.
A struct with methods which would satisfy an interface if any combination of any combination of method's return type's were changed to interface{} should satisfy the interface in question.
What would change in the language spec?
Please also describe the change informally, as in a class teaching Go.
you can return anything to satisfy an interface expecting an interface{} as a return type.
Show example code before and after the change.
With the proposed change, myStruct would satisfy the "myInterface" interface. currently it does not, as myOtherFunc returns a string, and not an interface{}
How would the language spec change?
See above. duplicate.
The text was updated successfully, but these errors were encountered: