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

go/types, types2: disable field accesses through type parameters for now #51576

Closed
griesemer opened this issue Mar 9, 2022 · 8 comments
Closed
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@griesemer
Copy link
Contributor

Field accesses through type parameters have been implemented and work, but are currently restricted to type parameters that have a core type.

This code

func g[P interface {
    struct{ f int }
    f() int
}](x P) {
    _ = x.f()
}

is currently accepted (as expected) because we don't determine that the type set for P is empty (the intersection of the single type struct{ f int } and the set of types that have method f() int is empty). We could change the embedded type element to ~struct{ f int } but in that case we cannot instantiate P because it's not possible to have a struct type with a field and a method with the same name.

This code

type F struct {
    f int
}

func g[P interface {
    ~struct{ F }
    f() int
}](x P) {
    _ = x.f()
}

is also accepted (as expected). Here it is possible to instantiate P because the field f and the method f are at different depths.

Note that in pre-1.18 Go, field and method names for a struct must be different (at the same level of embedding). It is not clear what the rules should be here.

These are just some of the questions that are brought up by this mechanism.

The current implementation could be described in the spec as follows:

Given a selector x.f, look up f following the usual rules. If no f is found, and if x is of type parameter type with a core type, look up f again on that core type and return that result, but only if it's a field.

It's not obviously clear if the generalization beyond core types (x.f is valid if it's valid for all types in a type set) will not lead to subtle surprises in behavior. We don't know if we should have restrictions with respect to method and field names that are the same. And so on.

In summary, while we do have an implementation, we don't fully understand the repercussions of this feature and how it would affect its generalization. At the same time we can always use methods as field accessors so there is a reasonable work-around.

The prudent decision for Go 1.18 is to disable this feature until we understand it well. We don't want to be in a situation where we have to support a potentially flawed mechanism for backward-compatibility.

@griesemer griesemer added this to the Go1.18 milestone Mar 9, 2022
@griesemer griesemer self-assigned this Mar 9, 2022
@gopherbot
Copy link

Change https://go.dev/cl/391135 mentions this issue: go/types, types2: disable field accesses through type parameters

@gopherbot
Copy link

Change https://go.dev/cl/391137 mentions this issue: spec: remove note re: field accesses on type literals

@gopherbot
Copy link

Change https://go.dev/cl/391274 mentions this issue: [release-branch.go1.18] doc/go1.18: document field access limitations for type parameters

@gopherbot
Copy link

Change https://go.dev/cl/391279 mentions this issue: _content/doc: update Go 1.18 release notes

gopherbot pushed a commit to golang/website that referenced this issue Mar 10, 2022
Document field access limitations for type parameters.

Also, remove some superfluous "currently" uses - the
time context is clear from the introductory paragraph
of the respective section.

For golang/go#51576.
For golang/go#47694.

Change-Id: If4c12f95f024894a9efb949dda9341d8ab0dc77e
Reviewed-on: https://go-review.googlesource.com/c/website/+/391279
Reviewed-by: DO NOT USE <iant@google.com>
Trust: Dmitri Shuralyov <dmitshur@google.com>
gopherbot pushed a commit that referenced this issue Mar 10, 2022
For #51576.

Change-Id: I43f72c3fb618e724d46360a70ab9f8abc3d63273
Reviewed-on: https://go-review.googlesource.com/c/go/+/391137
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@dmitshur dmitshur added the NeedsFix The path to resolution is known, but the work has not been done. label Mar 10, 2022
@gopherbot
Copy link

Change https://go.dev/cl/391355 mentions this issue: [release-branch.go1.18] go/types, types2: disable field accesses through type parameters

@bitfield
Copy link

By 'disable this feature', do you mean that it won't be possible to access the fields of a type parameter at all? So this example would no longer be valid: https://go.dev/play/p/bJ1QGu1MU38?v=gotip

@griesemer
Copy link
Contributor Author

@bitfield That is correct, your example doesn't work anymore (at least for Go 1.18). You can always use a method on the struct and the constraint. (As an aside, I have yet to see a convincing example for why this mechanism is crucial; especially because methods permit a work-around.)

There are simply too many unanswered questions around this mechanism for which we don't have solid answers yet. We don't want to be locked in through the backward compatibility guarantee if we make a mistake here. Note that the rules around field access are among the most subtle and complicated in the language spec and the implementation, even though for a user it may look "simple". Thanks.

@bitfield
Copy link

That's fine, thanks—I just wanted to clarify exactly what this change implies. I don't have a convincing use case for this either, but I'm looking at it from a writer's/teacher's point of view. It seems to be quite natural for people to try this quite early on when experimenting with constraints, and I need to be able to explain to them why this apparently straightforward thing isn't allowed. It looks easy from the programmer's side, if you see what I mean. "I know my parameter is a struct with these exact fields, why can't I access them?"

No writer likes to have to say "Here's something you can't do!" But I think it's going to be important to get out ahead of those inevitable questions.

gopherbot pushed a commit that referenced this issue Mar 11, 2022
…ugh type parameters

This is a feature that is not understood well enough and may have
subtle repercussions impacting future changes. Disable for Go 1.18.

The actual change is trivial: disable a branch through a flag.
The remaining changes are adjustments to tests.

Fixes #51576.

Change-Id: Ib77b038b846711a808315a8889b3904e72367bce
Reviewed-on: https://go-review.googlesource.com/c/go/+/391135
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit b8248fa)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391355
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
passionSeven added a commit to passionSeven/website that referenced this issue Oct 18, 2022
Document field access limitations for type parameters.

Also, remove some superfluous "currently" uses - the
time context is clear from the introductory paragraph
of the respective section.

For golang/go#51576.
For golang/go#47694.

Change-Id: If4c12f95f024894a9efb949dda9341d8ab0dc77e
Reviewed-on: https://go-review.googlesource.com/c/website/+/391279
Reviewed-by: DO NOT USE <iant@google.com>
Trust: Dmitri Shuralyov <dmitshur@google.com>
@golang golang locked and limited conversation to collaborators Jun 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

4 participants