-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/compile: corrupt error message for wrongly implemented generic interface #49579
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
Looks like go/src/cmd/compile/internal/types2/lookup.go Line 443 in c239790
leading to this hack failing to remove the go/src/cmd/compile/internal/types2/lookup.go Line 454 in c239790
|
OK, thanks, I will take a look and see how to fix it. |
@griesemer I looked at this, and to me it seems like this might be happening because of a types2 bug. As far as I can tell, the types2.Func that represents Q at line 16 (last line) has a object.typ of nil at the point where we're checking the 'return g[F]{}' statement, whereas it seems like it should have a Signature type which is the same as the type for the Q in the interface I. This manifests in going down the wrong conditional in missingMethodReason() and wrongType.typ being nil when we go to print it out. If you have time, maybe you can check this out (or happy to discuss with you directly), since it may be hiding a more serious bug. Or at least I need to understand better when a Func has a object.typ field that is nil. |
When calling "resolve", always enter the check.later branch (delayed processing), resulting in the "completeMethods" function is not actually called until "processDelayed".
go/src/cmd/compile/internal/types2/named.go Line 291 in 1d004fa
go/src/cmd/compile/internal/types2/lookup.go Line 129 in 1d004fa
== initFiles == == collectObjects == == packageObjects == ... crash.go:16:14: -- checking func Q (white, objPath = ) crash.go:16:8: . type g crash.go:16:8: . => g[F₃ interface{}] (under = struct{}) // *Named crash.go:16:7: . type *g[F] crash.go:16:9: . . type g[F] crash.go:16:8: . . . -- instantiating g with [%!s(*syntax.Name=&{F {{{0xc000562e70 16 10}}}})] crash.go:16:8: . . . . type g crash.go:16:8: . . . . => g[F₃ interface{}] (under = struct{}) // *Named crash.go:16:10: . . . . type F crash.go:16:10: . . . . => F₄ (under = interface{}) // *TypeParam crash.go:16:8: . . . => g[F₄] crash.go:16:9: . . => g[F₄] (under = ) // *Named crash.go:16:7: . => *g[F₄] // *Pointer crash.go:16:16: . type *any crash.go:16:17: . . type any crash.go:16:17: . . => interface{} // *Interface crash.go:16:16: . => *interface{} // *Pointer crash.go:16:14: => func (*g[F]).Q(*interface{}) (black) --- A : push back to check.later's processing list == processDelayed == crash.go:3:13: --- main: func() crash.go:4:1: --- crash.go:6:15: type set for interface{Q(*F₁)} crash.go:6:15: => {func (I[F interface{}]).Q(*F)} crash.go:10:17: type set for interface{Q(*interface{})} crash.go:10:17: => {func (I[F interface{}]).Q(*interface{})} crash.go:10:24: --- G: func[F₂ interface{}]() I[interface{}] crash.go:11:13: expr g[F]{} crash.go:11:10: . type g[F] crash.go:11:9: . . -- instantiating g with [%!s(*syntax.Name=&{F {{{0xc000562e70 11 11}}}})] crash.go:11:9: . . . type g crash.go:11:9: . . . => g[F₃ interface{}] (under = struct{}) // *Named crash.go:11:11: . . . type F crash.go:11:11: . . . => F₂ (under = interface{}) // *TypeParam crash.go:11:9: . . => g[F₂] crash.go:11:10: . => g[F₂] (under = ) // *Named ----- B : A is not processed yet. ... ... ----- C : processing A here. If make modification on the following line, when the input parameter ctxt of "expandNamed" is nil (check != nil && !isCtxtNil), don't entering the check.later branch, it can work right go/src/cmd/compile/internal/types2/named.go Line 290 in 1d004fa
crash.go:11:9: ERROR: cannot use g[F]{} (value of type g[F]) as type I[interface{}] in return statement: g[F] does not implement I[interface{}] (Q method has pointer receiver) |
That's probably "luck" -- if check is non-nil (i.e. we are in a type-checking pass), it should always be OK to defer actions using check.later. Most likely we're not eagerly expanding in some place where we need to. The clue that ctxt == nil in that case is helpful though. I will take a look at this today. |
Change https://golang.org/cl/364714 mentions this issue: |
The fix ended up (thankfully) being straightforward: during the type-checking pass methods found in missingMethod go through objDecl, because it's possible that they're not fully set up yet. But the check for methods with a pointer receiver bypassed objDecl. This may not have mattered before, but matters now that we lazily complete methods on instantiated types. |
I ran this code: https://gotipplay.golang.org/p/D0f2z4hHt4W
It correctly diagnoses that
g[F]
doesn't implement the required interface (becauseQ
is implemented on the pointer type, not the value type), but the error message that I see looks wrong:The text was updated successfully, but these errors were encountered: