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

types2, go/types: the scope of a type parameter identifier in a method of a generic type is too large #51503

Open
go101 opened this issue Mar 5, 2022 · 18 comments
Assignees
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@go101
Copy link

go101 commented Mar 5, 2022

What version of Go are you using (go version)?

$ go version
go version go1.18rc1 linux/amd64

What did you do?

type T[T any] struct {} // okay

func (T[T]) Bar() {} // error: T is not a generic type

What did you expect to see?

Compiles okay.

What did you see instead?

Fails to compile.

Honestly, the behavior conforms to the tip spec:

The scope of an identifier denoting a type parameter of a generic function or declared by a method receiver is the function body and all parameter lists of the function.

However, I think , for a method of a generic type, the scope should begin after the name of the generic type in the receiver, instead of beginning the start of receiver part.

@ALTree
Copy link
Member

ALTree commented Mar 5, 2022

cc @griesemer

@ALTree ALTree added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 5, 2022
@griesemer griesemer self-assigned this Mar 5, 2022
@griesemer griesemer added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Thinking and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Mar 5, 2022
@griesemer griesemer added this to the Go1.19 milestone Mar 5, 2022
@griesemer griesemer added the early-in-cycle A change that should be done early in the 3 month dev cycle. label Mar 5, 2022
@griesemer
Copy link
Contributor

Hm. We're treating the receiver declaration like any other parameter list (including type parameter lists) for simplicity. I suppose we could say:

The scope of an identifier denoting a type parameter of a generic function or declared by a method receiver starts after the function name and ends at the end of the function body.

This seems just as simple, perhaps even simpler. And it would avoid this arguably confusing error; even though I don't recommend choosing identifiers like this. But traditionally we have been paying attention to the ergonomics of scopes, so I think this warrants some attention.

But it seems that we should be able to make this change later (1.19) as I can't see how it would invalidate programs that are now possible.

(It's not an easy change, implementation-wise though, due to the way methods are represented: a method declaration corresponds to an instantiation of the method with the type parameters declared by the receiver which currently requires that the type parameters by the receiver are in scope in the receiver. This allows us to re-use a lot of code; but has also caused trouble. We were planning to change that part of the implementation independently. In any case, I wouldn't think this to be an impediment to making this spec change.)

@ianlancetaylor @findleyr thoughts?

@go101
Copy link
Author

go101 commented Mar 6, 2022

More precisely, the scope of type parameter identifier in a generic type method declaration should be the current definition excluding the receiver generic type name part.

The following error should be expected. The type parameter is declared firstly, then the value parameters (including receiver).

func (T1 T[T1]) Bar() {} 
// ./main.go:n:7: T1 redeclared in this block
//	./main.go:n:12: other declaration of T1

@griesemer
Copy link
Contributor

@go101 The suggestion for the new scope rule I gave seems good enough: the scope of ordinary parameters (including the receiver) is the function body and type parameters are also declared in that block. The same block cannot have the same identifier twice.

@go101
Copy link
Author

go101 commented Mar 11, 2022

A similar problem:

type C any

type _[C C] struct{} // cannot use a type parameter as constraint
func _[C C] () {}    // cannot use a type parameter as constraint

func _(C C) {} // okay

@ianlancetaylor
Copy link
Contributor

Yes, the scope of identifiers in a type parameter list is different from the scope of identifiers in a function parameter list. This is intended and documented. It's a necessary inconsistency, as we can't change function parameter lists, but we must permit forward references in a type parameter list.

@gopherbot
Copy link

This issue is currently labeled as early-in-cycle for Go 1.19.
That time is now, so a friendly reminder to look at it again.

@griesemer
Copy link
Contributor

The corresponding proposal has been accepted. This issue now tracks the implementation.

@griesemer griesemer added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. early-in-cycle A change that should be done early in the 3 month dev cycle. labels May 11, 2022
@griesemer griesemer changed the title spec: the scope of a type parameter identifier in a method of a generic type is too large types2, go/types: the scope of a type parameter identifier in a method of a generic type is too large May 11, 2022
@gopherbot
Copy link

Change https://go.dev/cl/405754 mentions this issue: spec: adjust scope of function/method type paramaters

gopherbot pushed a commit that referenced this issue May 12, 2022
Change scope rules per the accepted proposal #52038.
Match prose for type parameters of type declarations.
Fixing the implementation is tracked by #51503.

Fixes #52038.
For #51503.

Change-Id: Iebd88a82c896b7b2e8520cd514ef6a2cc903e807
Reviewed-on: https://go-review.googlesource.com/c/go/+/405754
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
@griesemer
Copy link
Contributor

We didn't get to this for 1.19: the necessary change is not small given the way receiver type parameters are processed at the moment, and requires some re-engineering (tracked via #51343). Moving to 1.20.

@griesemer griesemer modified the milestones: Go1.19, Go1.20 Jun 13, 2022
@smowton
Copy link

smowton commented Aug 18, 2022

I note that this change appears in the Go 1.19 release notes (https://go.dev/doc/go1.19) despite not making it into Go 1.19

@griesemer
Copy link
Contributor

@smowton The actual spec change was made. This issue tracks the fact the the compiler doesn't follow the spec.

@smowton
Copy link

smowton commented Aug 18, 2022

Heh, that might be worth mentioning in the notes -- Go is now supposed to support this snippet... but there are no implementations of the spec yet :)

@inliquid
Copy link

So release notes for go1.19 says this has been changed, however I see that problem still exists. This is the only opened issue with regard to it, another one locked.

Do above comments mean that change was made only to documentation and not implementation? Sounds weird. Why even mention it then?

@griesemer
Copy link
Contributor

The change was made in the documentation (spec) because we want the spec to be correctly describing the design (which it didn't). We haven't done the implementation yet, which requires #51343 first (and that one is non-trivial).

@griesemer
Copy link
Contributor

This depends on #51343. Moving to 1.21.

@griesemer griesemer modified the milestones: Go1.20, Go1.21 Nov 15, 2022
@griesemer
Copy link
Contributor

This depends on #51343 which moved to 1.22. Moving to 1.22.

@griesemer griesemer modified the milestones: Go1.21, Go1.22 May 25, 2023
@griesemer
Copy link
Contributor

This depends on #51343 which moved to 1.23. Moving to 1.23.

@griesemer griesemer modified the milestones: Go1.22, Go1.23 Nov 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

7 participants