(Adding the list back to CC; I assume you didn't mean to just send this
to me).
> When passing GenericType to something that expects GenericType(Text),
> it’s up to the user not to mess it up
Catching this kind of mistake is the whole point of a type system. If
you're going to make the argument that the type system shouldn't worry
too much about edge cases and just act as a linter, then maybe you can
claim that this isn't a big deal, but I think the premise that Kenton
and I have been assuming is that type soundness (the property that
well-typed programs do not have run-time type errors) is desirable here.
Obviously this isn't really achievable for the C++ implementation
overall since C++ itself fails this property, but it's probably worth
hanging on to both for other languages and because getting closer to the
goal in C++ is probably still a useful thing.
---
To get into the details of what the problem is: perhaps this is review
for everyone, but: the classic example of the problem with covariant
generics and mutability is demonstrated by this java program:
public class Main {
public static void main(String[] args) {
Integer[] ints = new Integer[4];
// assign by reference, so `objs` points to the same array
// as `ints`. Covariance (the notion that if A is a subtype
// of B, then A[] is a subtype of B[]) is rule by which java
// admits this statement:
Object[] objs = ints;
// And then because String is a subtype of Object, we can
// put a string in our list of integers through `objs`:
objs[0] = "OOPS";
}
}
As Kenton suggests, the example critically depends on pointer aliasing
for its unsoundness, so given that such aliasing is banned by the spec,
it may not be possible to construct such an example in a given message.
However, per my prior email it's not clear that you can't still run into
trouble by aliased references to the root struct of a message from the
rest of the program.
-Ian
Quoting Kuba Ober (2019-09-17 17:44:37)
> Either I’m not getting something or this is certainly meant to work with mutable types?
>
> Any field accepting a GenericType should accept an arbitrary specialization, at least in the implementations I know of. Of course the application itself may further constrain what types are allowed, but we’re talking about static type checking within CapnProto runtime implementation(s).
>
> I consider implementations that would not allow it to be buggy – otherwise the entire premise of generic types in CapnProto is IMHO broken. As far as I can divine intent from CapnProto documentation, the generics were designed so that an unparametrized type is a stand-in for all of its specializations, both in co- and contravariant directions. When passing GenericType to something that expects GenericType(Text), it’s up to the user not to mess it up – there are several such areas in CapnProto where the sender of a message and the receiver must agree on what type is actually sent.
>
> It’s up to the implementer to make it possibly type-safe, e.g. an implementation could store the parameter type id and do a single check when GenericType.Reader is coerced to GenericType<Text>.Reader, and so on.
>
> Slightly confused, Kuba
>
> > 16 sep. 2019 kl. 6:31 em skrev Ian Denhardt <
i...@zenhack.net>:
> >
> > Quoting 'Kenton Varda' via Cap'n Proto (2019-09-16 16:14:59)