Thank you for doing this, David. Your help is, as always, deeply
appreciated.

GC
On Tue, Jul 7, 2015 at 04:00 David Chisnall <thera...@sucs.org> wrote:

> For those who (like me) didn’t really pay attention to the WWDC last
> month, Apple has just sent patches for ‘lightweight’ (type-erasing) generic
> for Objective-C to the Clang list (see forwarded message).  These don’t
> require any runtime support, so they should Just Work™ with GNUstep, though
> we’ll want to add things to various headers to support them (these can be
> done with macros to support older compilers - I’ll put together a patch
> once it’s landed in clang and is easier to test).
>
> Given that Objective-C++ works well now with ARC, I’m less interested in
> this than I would have been 10 years ago - I tend to use C++ collection
> classes for Objective-C objects in new code - but it’s still quite a nice
> feature.
>
> David
>
> Hi all,
>
> Last month, Apple introduced a new lightweight generics system into
> Objective-C. The attached patch series provides the complete implementation
> of this feature, the related “kindof” types feature, supporting warnings,
> test-cases, and so on. It should get us back to the point where we can
> parse the headers for Apple’s latest SDKs.
>
> For those of you wondering what this whole lightweight generics thing is,
> I suggest either watching the following WWDC video starting at @21:45:
>
> https://developer.apple.com/videos/wwdc/2015/?id=401
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__developer.apple.com_videos_wwdc_2015_-3Fid-3D401&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=CnzuN65ENJ1H9py9XLiRvC_UQz6u3oG6GUNn7_wosSM&m=gksuXWwW39OdeK_NxENNyU46455v_XexMqDHmfEJNjA&s=ALq4TVlEqBaa3eyce5u1amIVjdR5youDJg0j05H4htQ&e=>
>
> or keep reading for an explanation.
>
> Lightweight generics allows Objective-C classes to be parameterized, e.g.,
> NSArray can be parameterized on the type of its elements:
>
> @interface NSArray<ObjectType> : NSObject
> -(ObjectType)objectAtIndex:(NSInteger)index;
> @end
>
> Objective-C classes, categories, extensions, and forward declarations can
> all specify type parameters. Naturally, the type parameters across
> different declarations associated with the same class must be consistent.
>
> For a given parameterized class, one can provide type arguments, e.g., to
> state the type of the elements of an NSArray:
>
> NSArray<NSString *> *strings;
> NSArray<NSNumber *> *numbers;
>
> Naturally, messaging an object of specialized type substitutes the type
> arguments for the type parameters, e.g.,
>
> [strings objectAtIndex: 0]; // produces an NSString *
> [numbers objectAtIndex: 0]; // produces an NSNumber *
>
> One can, of course, leave the type arguments unspecified:
>
> NSArray *array;
>
> Each of the types NSArray<NSString *>, NSArray<NSNumber *>, and NSArray
> are distinct types. There are implicit conversions between the
> “specialized” types (NSArray<NSString *>, NSArray<NSNumber *>) and the
> “unspecialized” type (NSArray *), but not between different specialized
> types. For example:
>
> array = strings; // okay, dropping type arguments
> numbers = array; // okay, adding type arguments
> strings = numbers; // not okay! NSArray<NSString *> and NSArray<NSNumber
> *> are incompatible types
>
> The “lightweight” in lightweight generics comes from the implementation
> model, which is based on type erasure (a la Java Generics). All of the type
> argument information is completely erased by IR generation, so this feature
> requires no runtime or metadata changes. Obviously, this—along with the
> implicit conversion rules above—means that some "obvious” errors will be
> missed by the type checker (and won’t be enforced by the runtime). For
> example, the sequence “array = strings; numbers = array;” is obviously
> bogus: the elements cannot be both NSStrings and NSNumbers. Sema won’t
> catch this, just like Sema wouldn’t catch an assignment chain that converts
> an NSNumber to an NSString by way of ‘id’.
>
> Type parameters have a few advanced features. First of all, they can have
> upper bounds, such that any type argument must be a subtype of the upper
> bound of the corresponding type parameter. For example:
>
> @interface MyMap<KeyType : id<NSCopying>, ObjectType>
> -(KeyType)firstKeyForObject:(ObjectType)object; // yes, this is a weird
> example; explanation below
> @end
>
> It’s an error to form a MyMap<T, U> where T isn’t a subtype of
> id<NSCopying>. When the type bound is omitted, it is “id”, i.e., all type
> parameters/arguments are all Objective-C objects. Type bounds are also
> important when using unspecialized types (e.g., MyMap *); we’ll come back
> to that later.
>
> Type parameters can also be co- or contra-variant, similarly to C#’s
> generic type parameters (see, e.g.,
> https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx)
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__msdn.microsoft.com_en-2Dus_library_dd799517-28v-3Dvs.110-29.aspx-29&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=CnzuN65ENJ1H9py9XLiRvC_UQz6u3oG6GUNn7_wosSM&m=gksuXWwW39OdeK_NxENNyU46455v_XexMqDHmfEJNjA&s=lLGp0NGVuw3Ee3R8nbuaDTRg6Jp-Pft4EJs7bdXavL4&e=>.
> This is particularly useful for the immutable collection classes, which
> we’ll use for exposition purposes. NSArray is actually declared as:
>
> @interface NSArray<__covariant ObjectType> : NSObject
> -(ObjectType)objectAtIndex:(NSInteger)index;
> @end
>
> Because ObjectType is covariant, NSArray<T> is implicitly convertible to
> NSArray<U> when T is a subtype of U, which allows, e.g.,
>
> NSArray<NSMutableString *> *mutStrings;
> NSArray<NSString *> *strings;
> strings = mutStrings; // okay, because ObjectType is covariant (and
> NSArray is an immutable collection)
>
> Contravariant type parameters go the opposite way, e.g., NSArray<T> is
> implicitly convertible to NSArray<U> when U is a subtype of T.
>
> Objective-C lightweight generics also involves a related feature called
> “kindof” types, which strike a balance between “id” and specific
> Objective-C pointer types. For example, given:
>
> __kindof NSString *kindofStr;
>
> we can implicitly convert to supertypes *and* subtypes, but not unrelated
> types. For example:
>
> NSObject *object = kindofStr; // okay, implicitly converting to supertype
> NSMutableString *mutString = kindofStr; // okay, implicitly converting to
> subtype
> NSNumber *number = kindofStr; // not okay! NSString and NSNumber are
> incompatible
>
> Naturally, the features compose: one can create an array of kindof types,
> e.g.,
>
> NSArray<__kindof NSValue *> *values;
>
> which can be *very* helpful when adopting lightweight generics. Kindof
> types are also important when working with unspecialized types. For
> example, let’s invent a class that only wants to work with subclasses of
> ‘View’:
>
> @interface SomeClass<T : View *> // T must be View or a subclass thereof
> - (T)view;
> @end
>
> As noted earlier, when we message SomeClass, we substitute in the type
> arguments for the type parameters, e.g.,
>
> SomeClass<Button *> *sc;
> [sc view]; // produces a "Button *"
>
> But what happens if we don’t have type arguments, because we’re messaging
> an object of type ’SomeClass *’? We produce a __kindoftype from the type
> bound, which gives us good static type information without forcing the user
> to introduce a large number of casts:
>
> SomeClass *sc;
> [sc view]; // produces a "__kindof View *"
>
>
> That’s most of it! I’ll be happy to answer any questions. Actual coherent
> documentation is forthcoming, but we wanted to get this implementation out
> there for people to play with.
>
> The patches are fairly large, since this is a nontrivial feature. I’ve
> broken it up into logical pieces, which are, roughly:
>
> 1) Type parameter parsing, ASTs, etc.
> 2) Type argument handling
> 3) Substitution of type arguments for parameters when using specialized
> types
> 4) Reworking our handling of the ternary operator on Objective-C pointer
> types
> 5) Interaction between C++ templates and Objective-C lightweight generics
> 6/7) Warnings for lightweight generics
> 8) Kindof types
> 9) Co- and contra-variant type parameters
> 10) Annoying workaround for old Clang versions that apparently still need
> to build with
>
> Detailed patch review should go to cfe-commits, so we can keep the
> discussion here more high-level.
>
> - Doug
>
>
>
>
>
> -- Sent from my STANTEC-ZEBRA
>
> _______________________________________________
> Gnustep-dev mailing list
> Gnustep-dev@gnu.org
> https://lists.gnu.org/mailman/listinfo/gnustep-dev
>
_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev

Reply via email to