You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have read the type parameters proposal several times without fully understanding it ;)
Mildly experienced at writing golang
Disclaimer: I'm putting this out quickly without a ton of detail because I realize the odds of this being accepted are really low this late in the go 1.18 process. If there's any chance this could be accepted, I'm willing to spend a bit more time fleshing it out this weekend. I expect perhaps it's too late to consider this, and I imagine that it was discussed to death in earlier rounds of generics -- but I would argue that some of that discussion happened prior to some of the simplification of type sets, so perhaps it wasn't as compelling?
If the language releases go 1.18 as is, then we are forever stuck with interfaces that can contain type sets and this proposal would no longer make sense as post-1.18 it would introduce multiple ways to do the same thing, which is not very go-like.
Disclaimer 2: I've only been really trying to use generics for 2 days, but I hope my fresh perspective is useful in this case
Proposal
Constraints that contain type sets may only be a "constraint" type instead of an "interface". For example:
The current rules for a interfaces with type sets would apply now to constraint types -- so a constraint could have both type sets and functions in its definition
Interfaces could still be used as generic constraints, but only to constrain functions, and not type + function
A constraint without a type set should probably be allowed, but can only be used in generic constraints
Would have to think more about the ramifications of this
Rationale
When I first started playing with generics, it took me some time before I needed to play with type sets. I created my own for something and since "it was an interface" I started trying to use it like an interface in the same places that you would normally use an interface (for example, #50813). But you can't do that, and it wasn't really clear to me immediately why that was.
From the type parameters proposal: "Go already has a construct that is close to what we need for a constraint: an interface type". But it's close. It's not the same, and shouldn't be the same.
I've definitely struggled at first to understand where I can use these new magic interfaces and where I can't use them. I believe that if they were separate things then it would be easier to bridge that gap.
Interfaces with type sets are not like other interfaces and cannot be used in most other places that an interface can be used
// nope, can't use interface here: interface contains type constraintsfuncUseInterface(cInterfaceWithTypeSets) {}
typeFoostruct {
// nope, can't use interface here: interface contains type constraintsIInterfaceWithTypeSets
}
typeGeneric[CMyConstraint] interface {
// surprise: interface contains type constraintsFn() C
}
Interfaces with type sets introduce ambiguity
It's also really easy to not notice that a particular interface is a constraint:
typeCinterface {
CoolThingFn()
}
What is that? Is that an interface that has an embedded interface, or is it an interface that can only be used as a constraint? Without knowing what CoolThing is, it's ambiguous to a human reading the code.
// surprise! compile error "interface contains type constraints"var_C
I don't know of many other places in golang where things are quite this ambiguous, but that could be a lack of experience.
Magic remote breakage
Here's another dumb idea I thought of -- which honestly this is a stretch, but possible in undisciplined projects. Let's say a library defines an interface that they only use as a generic constraint
typeLibraryInterfaceinterface {
Fn()
}
A user of the library finds it useful, extends it:
typeMyInterfaceinterface {
LibraryInterface
}
Or even worse, returns it because after all "its just an interface":
The next release of the library, the since the author was only using the interface as a generic constraint, decides to add a type set to the interface. Now any user that was trying to use that interface like a normal interface is broken.
Granted, this could still happen too if for example the library author changed the type of a particular name from an interface to a struct -- but it's a bit more egregious and more obviously a Bad Thing. If you're already only using an interface in a generic constraint context, "just" adding a type set is definitely a lot more non-obvious that you're going to break consumers of your library.
Why shouldn't you accept this proposal
Having a constraint type also implies that interfaces cannot be used as a constraint for a generic function/etc, which wouldn't be true.
Probably a lot of work on the compiler, would almost certainly delay go 1.18 and break any existing code written for the beta, and require a second beta release
Adding another thing to learn seems heavy handed (I argue the separation between interface and constraint is worth it!)
How often will these kind of interface constraints be used anyways? Is this really all that important?
Any future operations on type sets would probably be easier to parse/process since you don't have to grok whether it's an interface or an interface with constraints
The "interface contains type constraints" compiler error could be clearer now:
constraint cannot be used as a variable
constraint cannot be used as a function parameter
etc
Finally
Thanks for your consideration.
The text was updated successfully, but these errors were encountered:
This would give us two kinds of things that are very similar: interfaces and constraints. That would bring us back to a path that we were on before, in which we named (what we now call) constraints as contracts. See https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-contracts.md . When we presented that approach, many many people were concerned about the similarity between interface types and contracts--and they were actually more different than interfaces and constraints in this proposal. Because of those objections we moved away from contracts and consolidated on interface types.
Also, it's too late. After years of work we've accepted a proposal that uses interface types as constraints, and, while we could tweak that, we aren't going to radically change it at this point.
Therefore, we aren't going to adopt this change, and I'm going to close this issue. Sorry.
@wxolp I don't think this issue is a good place to discuss that topic. What you are discussing seems more like #41716, only updated to the current syntax and the notion of type sets.
Disclaimer: I'm putting this out quickly without a ton of detail because I realize the odds of this being accepted are really low this late in the go 1.18 process. If there's any chance this could be accepted, I'm willing to spend a bit more time fleshing it out this weekend. I expect perhaps it's too late to consider this, and I imagine that it was discussed to death in earlier rounds of generics -- but I would argue that some of that discussion happened prior to some of the simplification of type sets, so perhaps it wasn't as compelling?
If the language releases go 1.18 as is, then we are forever stuck with interfaces that can contain type sets and this proposal would no longer make sense as post-1.18 it would introduce multiple ways to do the same thing, which is not very go-like.
Disclaimer 2: I've only been really trying to use generics for 2 days, but I hope my fresh perspective is useful in this case
Proposal
Constraints that contain type sets may only be a "constraint" type instead of an "interface". For example:
This would no longer be allowed:
Rationale
When I first started playing with generics, it took me some time before I needed to play with type sets. I created my own for something and since "it was an interface" I started trying to use it like an interface in the same places that you would normally use an interface (for example, #50813). But you can't do that, and it wasn't really clear to me immediately why that was.
From the type parameters proposal: "Go already has a construct that is close to what we need for a constraint: an interface type". But it's close. It's not the same, and shouldn't be the same.
I've definitely struggled at first to understand where I can use these new magic interfaces and where I can't use them. I believe that if they were separate things then it would be easier to bridge that gap.
Interfaces with type sets are not like other interfaces and cannot be used in most other places that an interface can be used
Interfaces with type sets introduce ambiguity
It's also really easy to not notice that a particular interface is a constraint:
What is that? Is that an interface that has an embedded interface, or is it an interface that can only be used as a constraint? Without knowing what CoolThing is, it's ambiguous to a human reading the code.
I don't know of many other places in golang where things are quite this ambiguous, but that could be a lack of experience.
Magic remote breakage
Here's another dumb idea I thought of -- which honestly this is a stretch, but possible in undisciplined projects. Let's say a library defines an interface that they only use as a generic constraint
A user of the library finds it useful, extends it:
Or even worse, returns it because after all "its just an interface":
The next release of the library, the since the author was only using the interface as a generic constraint, decides to add a type set to the interface. Now any user that was trying to use that interface like a normal interface is broken.
Granted, this could still happen too if for example the library author changed the type of a particular name from an interface to a struct -- but it's a bit more egregious and more obviously a Bad Thing. If you're already only using an interface in a generic constraint context, "just" adding a type set is definitely a lot more non-obvious that you're going to break consumers of your library.
Why shouldn't you accept this proposal
constraint
type also implies that interfaces cannot be used as a constraint for a generic function/etc, which wouldn't be true.Other
comparable
#50791 -- comparable becomes a constraint type, instead of a magic interfaceconstraint cannot be used as a variable
constraint cannot be used as a function parameter
Finally
Thanks for your consideration.
The text was updated successfully, but these errors were encountered: