-
Notifications
You must be signed in to change notification settings - Fork 117
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
deprecated reflect mode has been replaced with import mode #198
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey! Thank you for this PR! We're excited about this change. We took a first pass and have some initial comments. We're going to do some additional testing on this and come back soon for more review.
One high level comment I wanted to raise was - with Go 1.23, go/types introduced Alias. Can we add test cases that try to load aliases to interfaces and verify this will work?
This already works without explicitly specifying an alias. This works thanks to the Underlying method. Example of generated mock for alias: mock/mockgen/internal/tests/import_mode/mock/interfaces.go Lines 297 to 434 in 703a35f
And, yes, i tested it in compile-time:
Generated mock successfully implements alias. |
@tulzke, when I run mockgen's tests on go1.23.1, or with GODEBUG=gotypesalias=1, I get the following failure:
This is because |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @tulzke - thanks for the updates and sorry for the delay. Took another pass.
Forgot to add - since |
Why we can't just update go up to 1.23 in go.mod? This is the latest stable version. If we make different implementations for different versions of Go, it will be noticeably more difficult to maintain. |
I'm gonna ask other maintainers their thoughts here because I'm actually not super sure myself. cc: @sywhang @r-hang @tchung1118. I believe using 1.23 in go.mod would force anybody who wants to use the next release to upgrade to go1.23. We can technically bump the version of |
As moving to go1.23 would be considered a breaking change, it might make sense to release as v2 which would force users to move forward manually. That would allow the old system to work with older versions but force users to move forward with a "modern" version. I've been watching/waiting/using this change for a few weeks now. For users that want to stay up-to-date with Go versions and latest protoc changes, not merging this change is causing real headaches. |
This change updates all `go.mod` and ci workflows to only support go1.22 and go1.23. Although this will force users to upgrade to go1.22 to use the next release, it is technically in line with our release policy (see: https://github.com/uber-go/mock?tab=readme-ov-file#supported-go-versions) and will allow us to merge uber-go#198 without using build tags for references to the new `*types.Alias` and `types.Unalias()`.
Chatted about build tags vs. go.mod update internally - we think it's fine to update This is technically in line with our release policy and will avoid some ugly code in the big switch statement as @tulzke mentioned.
As a policy, we don't typically do 2.0 releases. If something is truly a breaking change we don't usually even consider it. In this case however - I'm not sure dropping support for Go versions that aren't even supported themselves upstream qualifies as a breaking change, so I think it's fine to update |
This change updates all `go.mod` and ci workflows to only support go1.22 and go1.23. Although this will force users to upgrade to go1.22 to use the next release, it is technically in line with our release policy (see: https://github.com/uber-go/mock?tab=readme-ov-file#supported-go-versions) and will allow us to merge #198 without using build tags for references to the new `*types.Alias` and `types.Unalias()`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @tulzke - this is looking great! Thanks for your updates. I did a final fine-toothed review over this, but other than these last couple of comments/questions this LGTM.
ci/test.sh
Outdated
@@ -1,6 +1,9 @@ | |||
#!/bin/bash | |||
# This script is used to ensure that the go.mod file is up to date. | |||
|
|||
# Compatibility for Go 1.22 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand on why this is needed? Ideally, we'd want to support Go 1.22 w/o the GODEBUG variable set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have already generated mocks for aliases. Without gotypesalias=1, mocks are generated without aliases.
Example from failed test:
< func (c *MockEarthHumanPopulationCall) Return(arg0 int) *MockEarthHumanPopulationCall {
---
> func (c *MockEarthHumanPopulationCall) Return(arg0 import_mode.HumansCount) *MockEarthHumanPopulationCall {
HumansCount
here - alias for int
. On 1.23 and 1.22 with GODEBUG=gotypealias=1
mockgen wiil generate mocks with correct types. On native 1.22 it wil generate int
instead of import_mode.HumansCount
.
Tests on 1.22 and 1.23 have different behavior now due to aliases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood - let's keep this here then. Can you just add this brief explanation into the test script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tested it now. And with go 1.22 in go mod it does not work with aliases as i expected.
$ go version
go version go1.23.1 darwin/arm64
$ cat go.mod | grep "go 1."
go 1.22
$ cd mockgen
$ go build . && cp mockgen /Users/USERNAME/go/bin/mockgen # copy binary to PATH
$ cat internal/tests/import_mode/go.mod | grep "go 1." #checking go version in nested go module
go 1.23
$ cd internal/tests/import_mode
$ cat interfaces.go| grep "AddHumans"
AddHumans(HumansCount) []Human
$ go generate ./...
$ cat mock/interfaces.go | grep "AddHumans(arg0" #must have HumansCount and Human instead of int and Primate
func (m *MockEarth) AddHumans(arg0 int) []import_mode.Primate {
func (mr *MockEarthMockRecorder) AddHumans(arg0 any) *MockEarthAddHumansCall {
In my case it works only after i changed go version in go.mod and rebuild binary.
Do you have any ideas how to support go 1.22 and alias types together?
Hey @tulzke - I'm sorry, I mistakenly overrode your remote branch's I think I'm able to re-instate it/re-open the PR how it was by pushing the correct |
I can't re-open this PR, so i created the new one: |
resolves #175
resolves #197
resolves #128
It is impossible to create an mock for a generic interface via reflect mode, because it is impossible to compile a generic type without instantiation.
This PR replaces the reflect mod for parsing using go/types.
All exists mocks have been regenerated and the tests have been passed. But since this radically changes the behavior of reflect mode, I would be grateful if there are those who want to add additional test cases that I did not provide.
We can also come up with another name instead of import mode.
benefits: