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

spec: "strictly comparable" and "type constraints". #59104

Open
gitspeaks opened this issue Mar 17, 2023 · 7 comments
Open

spec: "strictly comparable" and "type constraints". #59104

gitspeaks opened this issue Mar 17, 2023 · 7 comments
Assignees
Labels
Documentation NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@gitspeaks
Copy link

#1 According to the Language Specification:

A type is strictly comparable if it is comparable and not an interface type nor composed of interface types. Specifically:

Boolean, numeric, string, pointer, and channel types are strictly comparable.
Struct types are strictly comparable if all their field types are strictly comparable.
Array types are strictly comparable if their array element types are strictly comparable.
Type parameters are strictly comparable if all types in their type set are strictly comparable."

Consider changing to:

A type is strictly comparable if it is comparable and not a basic interface type nor composed of 
interface types. Specifically: 

Boolean, numeric, string, pointer, and channel types are strictly comparable. 
Struct types are strictly comparable if all their field types are strictly comparable. 
Array types are strictly comparable if their array element types are strictly comparable. 

Type constraints are strictly comparable if their elements are strictly comparable thus 
Type parameters (not to be confused with Type arguments) are strictly comparable if all 
types in their type set are strictly comparable. 

Rational: By definition “A type constraint is an interface” and the doc explicitly mentions: “strictly comparable type constraint” under "Satisfying a type constraint".

#2 Consider capitalizing each instance of the word "Comparable" where it references the property of comparability, as described in the "Comparison Operators" section. The term "comparable" appears in other contexts, such as "strictly comparable" and the comparable Interface", so due to the repetition of the word, it can be difficult to follow.

#3 Addressing a related but distinct issue, under "General Interfaces" it is stated that: "The type set of a non-interface type term is the set consisting of just that type."

The following example is provided:

// An interface representing only the type int 
type Foo interface { int }

By definition, this interface is a non-basic interface, which means it can only appear in type constraints. However, the rationale for an interface of this form is not immediately apparent. Please clarify in the spec the circumstances in which declaring an interface with a non-interface type term would be sensible.

@ianlancetaylor
Copy link
Contributor

CC @griesemer

  1. We don't have to define comparability of interface types that are not basic interface types, as it is invalid to have values of such types. I don't understand the point of your rewrite of the final sentence, about type parameters.

  2. We aren't going to capitalize Comparable in the spec, that is not grammatical English.

  3. The spec needs to define the type set of int in order to define the type set of int | float.

@ianlancetaylor ianlancetaylor added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Mar 17, 2023
@gitspeaks
Copy link
Author

1. We don't have to define comparability of interface types that are not basic interface types, as it is 
   invalid to have values of such types.  

The issue is not about defining the comparability of interface types that are not basic, but rather about maintaining consistency in terminology. If "a type is strictly comparable if it is comparable and not an interface type," then how can a "strictly comparable type constraint" exist when a type constraint is an interface?

I don't understand the point of your rewrite of the final sentence, about type parameters.

The point is to clarify that in this instance type parameters obtain their type sets from Type constraints (interfaces types that are strictly comparable, as apposed to type argument, such as interface type arguments which are not strictly comparable)

2. We aren't going to capitalize Comparable in the spec, that is not grammatical English.

In my opinion, the way the word "comparable" is used in the specification strongly suggests a domain-specific term. Its meaning is not immediately obvious (the document even links it to "Comparison Operators"), so I don't see any issue in treating it as a capitalized term. Alternatively, you could write "comparable type." In any case, the goal is to help the reader keep track of which "comparable" is being discussed.

3. The spec needs to define the type set of `int` in order to define the type set of `int | float`.

Why? Why is it necessary to define the type set of int | float? Why does the compiler even accept:

type MyType[T int] struct {
        field T
}

which is exactly:

type MyType struct {
        field int
}

@ianlancetaylor
Copy link
Contributor

The issue is not about defining the comparability of interface types that are not basic, but rather about maintaining consistency in terminology. If "a type is strictly comparable if it is comparable and not an interface type," then how can a "strictly comparable type constraint" exist when a type constraint is an interface?

I see, I missed that you changed the text from referring to a "type parameter" to referring to a "type constraint." I do think that it's important to define when a type parameter is strictly comparable. It's not clear to me whether it is important to define when a type constraint is strictly comparable. Your suggested modified text doesn't explain when a type parameter is strictly comparable. Or so it seems to me.

...I don't see any issue in treating it as a capitalized term.

Are there other such capitalized terms in the spec today? If not, let's not add one.

Why is it necessary to define the type set of int | float?

The definition of the type set of T1 | T2 is that it is the union of the type sets of T1 and T2. Therefore, we need to define what those type sets are.

@gitspeaks
Copy link
Author

It's not clear to me whether it is important to define when a type constraint is strictly comparable.

Well, the spec does mention the term "strictly comparable type constraint," so it begs the question, what is it?

Your suggested modified text doesn't explain when a type parameter is strictly comparable. Or so it seems to me.

The spec states: "An interface type defines a type set".
The spec states: "A type constraint is an interface". This implies that a type constraint defines a type set.
The spec states: "Each type parameter has a corresponding (meta-)type which is called its type constraint". This implies that each type parameter has a type constraint that defines a type set.

The spec states: "Type parameters are strictly comparable if all types in their type set are strictly comparable." This implies that type parameters are strictly comparable if all the types in the type set defined by their type constraints are strictly comparable.

What do you call a type constraint that defines a type set where all types are strictly comparable other than a strictly comparable type constraint?

Are there other such capitalized terms in the spec today? If not, let's not add one.

Agreed, so I suggest using the term "comparable types" linking to the "Comparison Operators" section:

Compare:

Original: "Even though interfaces that are not type parameters are comparable, they are not strictly comparable and therefore they do not implement comparable. However, they satisfy comparable.

vs.

Revised: Even though interfaces that are not type parameters are comparable types, they are not strictly comparable and therefore they do not implement the comparable interface. However, they satisfy the comparable interface.

The definition of the type set of T1 | T2 is that it is the union of the type sets of T1 and T2. Therefore, we need to define what those type sets are.

It seems to me that type Foo interface { int } is allowed for completeness rather than any practical application. I won't argue with that. However, I do recommend clarifying this point in the spec.

@ianlancetaylor
Copy link
Contributor

It seems to me that type Foo interface { int } is allowed for completeness rather than any practical application.

Yes.

I won't argue with that. However, I do recommend clarifying this point in the spec.

The spec is intended to be readable but it is not a tutorial.

I'll leave the other points for @griesemer .

@gitspeaks
Copy link
Author

Please consider the following revised statement:

"Type constraints are deemed strictly comparable if their elements are strictly comparable and the comparable interface is not included. In this case, the associated type parameters are also considered strictly comparable."

This occurs because incorporating the comparable interface in a type constraint effectively relaxes the constraint, allowing any comparable type as a type argument provided that it implements all other interfaces included in the type constraint.

@griesemer griesemer self-assigned this Mar 20, 2023
@griesemer griesemer added this to the Go1.21 milestone Mar 20, 2023
@griesemer
Copy link
Contributor

Marked for 1.21 so it remains visible. Not sure yet if we need to make any changes.

@seankhliao seankhliao added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. and removed WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. labels Mar 25, 2023
@griesemer griesemer modified the milestones: Go1.21, Go1.22 Jul 19, 2023
@griesemer griesemer modified the milestones: Go1.22, Go1.23 Nov 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

4 participants