-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
go/types,cmd/compile/internal/types2: shared type expressions are evaluated once per variable #46208
Comments
Indeed this affects both go/types and types2. Here's the relevant TODO: I think this could be done, but we should probably handle decls with init exprs as well, which IIRC would be a non-trivial refactoring. |
Edit: Disregard. It appears that the problem I ran into with structs and signatures is that types2 evaluates the field type expressions just once each, but cmd/compile was evaluating them multiple times. |
For fun, I created these two test cases:
cmd/compile and gccgo both appear to go exponential on the first test. go/types handles it instantly. cmd/compile handles the second one instantly. gccgo and go/types take somewhat longer, but still complete within a few seconds. (To be fair to gccgo, I'm running it from a network file system, and it takes a few seconds to compile even a file with just I tried a few more minor variations on the idea, but couldn't figure out a way to make go/types go exponential. |
Change https://golang.org/cl/320789 mentions this issue: |
This CL updates noder and typecheck to avoid a couple instances of redundant evaluation of type expressions: 1. When noding struct fields or parameter tuples, check for syntax.Type reuse between adjacent fields and then reuse the corresponding ir.Node type expression. It would perhaps be even better to avoid re-noding the type expression too, but noder's days are numbered anyway, so I'd rather be minimally invasive here. 2. When importing an empty interface, reuse the same cached empty interface instance that is used for empty interfaces that appear in source. This matches types2's behavior, which uses a single types2.Interface instance for all empty interfaces. These changes are motivated by making it possible to migrate from typecheck to types2 while passing toolstash -cmp. Updates golang#46208. Change-Id: Ia6458894494464d863181db356f3284630c90ffe
This CL updates noder and typecheck to avoid a couple instances of redundant evaluation of type expressions: 1. When noding struct fields or parameter tuples, check for syntax.Type reuse between adjacent fields and then reuse the corresponding ir.Node type expression. It would perhaps be even better to avoid re-noding the type expression too, but noder's days are numbered anyway, so I'd rather be minimally invasive here. 2. When importing an empty interface, reuse the same cached empty interface instance that is used for empty interfaces that appear in source. This matches types2's behavior, which uses a single types2.Interface instance for all empty interfaces. These changes are motivated by making it possible to migrate from typecheck to types2 while passing toolstash -cmp. Updates golang#46208. Change-Id: Ia6458894494464d863181db356f3284630c90ffe
This CL updates noder and typecheck to avoid a couple of instances of redundant evaluation of type expressions: 1. When noding struct fields or parameter tuples, check for syntax.Type reuse between adjacent fields and then reuse the corresponding ir.Node type expression. It would perhaps be even better to avoid re-noding the type expression too, but noder's days are numbered anyway, so I'd rather be minimally invasive here. 2. When importing an empty interface, reuse the same cached empty interface instance that is used for empty interfaces that appear in source. This matches types2's behavior, which uses a single types2.Interface instance for all empty interfaces. These changes are motivated by making it possible to migrate from typecheck to types2 while passing toolstash -cmp. Updates #46208. Change-Id: Ia6458894494464d863181db356f3284630c90ffe Reviewed-on: https://go-review.googlesource.com/c/go/+/320789 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Trust: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
@mdempsky This is in the 1.18 milestone; time to move to 1.19? Thanks. |
@mdempsky This is in the 1.19 milestone; time to move to 1.20? Or Backlog? Thanks. |
Too late for 1.19. But we should probably look into this. Moving to 1.20. |
Too late for 1.22. |
Moving to 1.24. We didn't get to this. |
If a VarDecl has an explicit type expression, it will get evaluated once for each declared variable. So if you have a VarDecl like
var x, y interface { M() }
you end up with two different*types2.Interface
objects.I ran into this because I wanted to map all
types2.Type
objects (that appeared in source) back to some syntactic element, so my initial approach was to just walk the AST looking for type expressions and then usingInfo.Types[expr].Type
to get thetypes2.Type
object and insert them into amap[types2.Type]syntax.Expr
map.However, this approach missed some types, because of VarDecls with multiple variables and an explicit type expression.
I don't think this is strictly a violation of the types2 API (you're supposed to use types2.Identical), but I think it would be nice and less surprising if there was a 1:1 correspondance.
I assume this also affects go/types.
/cc @griesemer @findleyr
The text was updated successfully, but these errors were encountered: