On Fri, Jun 19, 2020 at 9:31 AM Bryan C. Mills <bcmi...@google.com> wrote: > > On Fri, Jun 19, 2020 at 1:30 AM Ian Lance Taylor <i...@golang.org> wrote: >> >> This code is acting as though, if ordinary interface types could have >> type lists, it would be OK to write >> >> func Add2(x, y SmallInt) SmallInt { return x + y }ᵢ >> >> That is not OK, even though SmallInt has a type list. Even though >> every type in theSmallInt type list supports +, they don't support + >> with every other type in the type list. > > > Yes, that is exactly my point: the fact that that program is invalid implies > that type-list interfaces are not consistent with the semantics of other > interface types.
I'm sure that I don't really understand what you are saying. But from my perspective using a type list in an interface type used as a type constraint permits certain operations in that generic function. That is a specific feature of generic functions. You seem to be trying to extend that capability to non-generic functions. But that doesn't work. A generic function permits saying that certain values are exactly the same type. There is no way to say that using interface types in a non-generic function. The fact that this function is invalid: func Add2(x, y SmallInt) SmallInt { return x + y } is no more interesting than the fact that this function is invalid: func Add2(type T1 SmallInt, T2 SmallInt)(x T1, y T2) T1 { return T1(x + y) } You can only use the + operator if you have the same underlying type on both sides. Neither of these variants of Add2 guarantee that. Only a generic function can guarantee that, and that guarantee is entirely separate from whether constraints are interfaces, or contracts, or something else entirely. > As a run-time interface type, MediumInt clearly must implement itself (that > is a fundamental property of interface types), and SmallInt (I claim) must > also implement MediumInt because the concrete values it allows are a strict > subset of the values allowed for MediumInt. (Otherwise, interface types seem > incoherent as a concept.) > > The constraint-satisfaction rule for ordinary (non-type-list) interfaces, > both in the current draft design and in FGG, is very simple: “Implementing a > constraint is simply implementing the interface type.” (In the FGG paper, > constraint-satisfaction is formalized as the judgement “Φ :=Δ φ”, which is > defined using a single, uniform rule.) > > However, type-list interfaces in the current design have a different, more > complex rule: “[the type argument must implement the methods in the interface > type and] the underlying type of the type argument must be identical to the > underlying type of one of the types in the type list.” That is a much > stronger requirement than “simply implementing the interface type”, and it > implies that for an interface I that happens to include a type-list, there is > no way to express the simple constraint “T implements interface I” without > also adding the secondary constraint that “the underlying type of [T] must be > … one of types in the type list”. > > Similarly, the type-checking rule for non-type-list interfaces is simple: > “assuming that the type arguments are distinct types that each implement > their constraint interfaces, check the body of the declaration”. In contrast, > the type-checking rule for type-list interfaces has an extra condition: > “assuming that the type arguments are distinct type that each implement their > constraint interfaces, and assuming that each argument whose constraint is a > type-list has an underlying type identical to one of the types in the list, > check the body of the declaration”. That all sounds right to me. > Because the rules for type-list interfaces always have an extra condition > beyond “simply implementing the interface type”, we would be locked into at > least one of the following limitations on the evolution of the language: > > A type-list interface can never be used as a type argument. > Or, a type parameter of an interface type can never be allowed as the > constraint of another type parameter, nor embedded in the constraint of > another type parameter. I don't understand what the second limitation means. The current design draft has no way to require that a type parameter have an interface type. Can you give an example of what you mean? > Otherwise, we would break the substitution property: the meaning of a > type-list interface would depend upon whether it was written literally in the > source code or passed as a type argument. (That is: the meaning of a generic > declaration instantiated with a given list of argument types would be > different from the meaning of the same declaration with some of its actual > arguments substituted for the corresponding parameters.) Again I'm sure that I don't understand what you are saying. My initial reaction is that of course the meaning of a type-list interface depends on whether it is used as a type constraint or is passed as a type argument. Those are two entirely different operations. You can't use a type parameter as a type constraint. I suppose you could regard that as a limitation of the system, but it's an intentional one. If a type parameter can be a type constraint, then there is no contract for the generic function: it has ceded control over what type arguments are permitted. It is no longer possible to compile the generic function separately. It's a very different semantic model. > I think both of those limitations are severe. > > If a type-list interface cannot be used as a type argument, then type-list > interfaces are not really “interface types” — in fact, they are not “types” > at all, because they cannot be used as even unrestricted type arguments. > On the other hand, if parameters of interface type cannot be used as > constraints for other type parameters, then the constraints are not really > “interface types” in general, but rather something more restricted. (In the > current draft we have no explicit way to express that a parameter is “of > interface type” in general, but it doesn't seem like a stretch to make > parameters-as-subtyping-constraints work in general.) I don't know if I would say that they are something more restricted, exactly, but using them in a different way has a different effect. > To me, this all suggests that the “underlying type” sort of constraint should > be conceptually and syntactically different from the “simply implementing the > interface type” sort of constraint. I don't necessarily object, if we can find the right name and syntax, but I don't understand how that would be effectively different from what the design draft says today. We would say that a type constraint can be an interface type, or it can be this other thing that is an interface type plus a list of types. Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcU7c1T%3DKYA6YM2v0RnWTTn0b0A3prJ-k2%2Bhraw5VDUNHg%40mail.gmail.com.