Skip to content
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

cmd/compile: odd type error reported on the wrong line #49441

Closed
aarzilli opened this issue Nov 8, 2021 · 13 comments
Closed

cmd/compile: odd type error reported on the wrong line #49441

aarzilli opened this issue Nov 8, 2021 · 13 comments
Labels
generics NeedsInvestigation
Milestone

Comments

@aarzilli
Copy link
Contributor

@aarzilli aarzilli commented Nov 8, 2021

This code:

package main

type pointerToT[T any, PT pointerToT[T, PT]] interface{
	*T
}

func F[T any, PT pointerToT[T, PT]](n, nn PT) {
}

compiles just fine, however adding a new function definition, calling F:

package main

type pointerToT[T any, PT pointerToT[T, PT]] interface{
	*T
}

func F[T any, PT pointerToT[T, PT]](n, nn PT) {
}

func WrapF[A any, PA pointerToT[A, PA]](n, nn PA) {
	F(n, nn)
}

Causes the error: ./buggy.go:7:15: PT does not match *T on the line declaring F. It's weird that declaring a function would cause a different function to no longer typecheck correctly, I think this error was meant to be reported on the call to F.
It's also unclear what the problem is, shouldn't the type inference work correctly? Manually instantiating F as F[A, PA](n, nn) makes the error go away.

@cagedmantis cagedmantis added NeedsInvestigation generics labels Nov 9, 2021
@cagedmantis cagedmantis added this to the Backlog milestone Nov 9, 2021
@cagedmantis
Copy link
Contributor

@cagedmantis cagedmantis commented Nov 9, 2021

/cc @randall77 @griesemer

@gopherbot
Copy link

@gopherbot gopherbot commented Nov 9, 2021

Change https://golang.org/cl/362634 mentions this issue: cmd/compile: fix type error reported on the wrong line

@hanchaoqun
Copy link
Contributor

@hanchaoqun hanchaoqun commented Nov 10, 2021

I guess the type inference has a bug, since the PT , PA , *T can be inferred from each other, and this code should work with no error. Seems the reason for the error comes from both of the “index” and “nify” functions does not dereference the pointer for TypeParam

func (d *tparamsList) index(typ Type) int {

switch i, j := u.x.index(x), u.y.index(y); {

@hanchaoqun
Copy link
Contributor

@hanchaoqun hanchaoqun commented Nov 10, 2021

bug here , when x = PA , y = *T, the *T is the a single defined type in the constraint, PA should look into it's constraint too.

@Jason7602
Copy link
Contributor

@Jason7602 Jason7602 commented Nov 10, 2021

If we just change the above code to this way, it doesn't needs a dictionary to Call F and have no error message. Cause it can infered the PA is type of *T from the first parameter.

package main

type pointer[T any, PT pointer[T, PT]] interface{
*T
}

func F[T any, PT pointer[T, PT]](n T, nn PT) {
}

func WrapF[A any, PA pointer[A, PA]](n A, nn PA) {
	F(n, nn) 
}

But if the both parameter Type is PT, it seems that the compile do not to infer if it haven't a dictionary to call F and cause such error message, actually it can infered, cause PA is the type of pointerToT, to this extent, may @hanchaoqun did the right analysis.
But I not sure whethe this is a call constraint and it should have been add a dictionary to call functions in this scenario.

@gopherbot
Copy link

@gopherbot gopherbot commented Nov 10, 2021

Change https://golang.org/cl/362776 mentions this issue: cmd/compile: unifier.unify look deep for single defined type in constraint

@hanchaoqun
Copy link
Contributor

@hanchaoqun hanchaoqun commented Nov 10, 2021

Ah...type looping through the type parameter list is not allowed since https://go-review.googlesource.com/c/go/+/361922
, the error changed:

$ go tool compile ../test/typeparam/issue49441.go
../test/typeparam/issue49441.go:9:6: invalid recursive type pointerToT
        ../test/typeparam/issue49441.go:9:6: pointerToT refers to
        ../test/typeparam/issue49441.go:9:6: pointerToT
../test/typeparam/issue49441.go:17:3: cannot infer T (../test/typeparam/issue49441.go:13:8)

The following is a test case eliminate circular references, which report the same error : "PT does not match *T":

package main

type pointerToT[T any] interface{
*T
}

func F[T any, PT pointerToT[T]](n, nn PT) {
}

func WrapF[A any, PA pointerToT[A]](n, nn PA) {
	F(n, nn)
}

@aarzilli
Copy link
Contributor Author

@aarzilli aarzilli commented Nov 10, 2021

The type inference bug is no longer a bug, unless someone can reproduce it without using a type cycle. The wrong line number for the error is a duplicate of #45985.

@hanchaoqun
Copy link
Contributor

@hanchaoqun hanchaoqun commented Nov 10, 2021

I think it still a bug for the following code :

package main

type pointerToT[T any] interface{
*T
}

func F[T any, PT pointerToT[T]](n, nn PT) {
}

func WrapF[A any, PA pointerToT[A]](n, nn PA) {
	F(n, nn)
}

error: "PT does not match *T"

Could you please reopen this ticket?

@aarzilli aarzilli reopened this Nov 10, 2021
@hanchaoqun
Copy link
Contributor

@hanchaoqun hanchaoqun commented Nov 13, 2021

@dr2chase I make another reproducer, which compile error also occurs (should work with no error), and seems this kind of generic parameter constrained to be a pointer is very commonly used in container libraries such as "iterator" "list" etc. Maybe need be labeled as release-blocker?

package main

type pointerToT[T any] interface {
        *T
}

func innerFunc[T any, PT pointerToT[T]](ptr PT) {
}

func ExportFunc[A any, PA pointerToT[A]](ptr PA) {
        innerFunc(ptr)
}

$ go build crash.go
# command-line-arguments
./crash.go:13:23: PT does not match *T

@griesemer
Copy link
Contributor

@griesemer griesemer commented Nov 13, 2021

I agree that the error message is confusing. I disagree that the last example should work without error, at least with the current implementation. Here's a slightly stripped-down version:

func f[T any, PT *T](x PT) {}

func _[T any, PT *T](x PT) {
        f(x)
}

Note that x is of type PT which is not a pointer type, it's a type parameter. At the moment, we do not look inside type parameter constraints when attempting type inference. Note that:

func f[T any, PT *T](x PT) {}

func _[T any](x *T) {
        f(x)
}

works fine, so I am not sure why the PT type argument is needed in the first place.

@griesemer griesemer self-assigned this Nov 13, 2021
@griesemer griesemer removed this from the Backlog milestone Nov 13, 2021
@griesemer griesemer added this to the Go1.18 milestone Nov 13, 2021
@griesemer
Copy link
Contributor

@griesemer griesemer commented Nov 13, 2021

At this point this issue it about a confusingly placed error message. For:

package p

func f[T any, P *T](x P) {}

func _[P *int](x P) {
        f(x)
}

we get the error:

testdata/manual.go2:3:15: P does not match *T

which is confusing.

I agree that https://go-review.googlesource.com/c/go/+/362634/ (thanks!) provides a better error position, but the error is still confusing.

I will file a separate issue for "deep inference" where we look inside a type parameter.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Nov 13, 2021

Actually, just noticing the reference #45985 as duplicate (for the incorrect position of the error), so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
generics NeedsInvestigation
Projects
None yet
Development

No branches or pull requests

6 participants