[LLVMbugs] [Bug 16749] New: Allow ObjC properties with one type publicly and a subtype privately

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Jul 30 09:28:59 PDT 2013


http://llvm.org/bugs/show_bug.cgi?id=16749

            Bug ID: 16749
           Summary: Allow ObjC properties with one type publicly and a
                    subtype privately
           Product: clang
           Version: trunk
          Hardware: Macintosh
                OS: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: rix.rob at gmail.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

I want to have a property with one type publicly and a subtype of it privately.
I want private accesses to be type-safe with respect to the subtype, but public
accesses to be type safe with respect to the supertype.

Case in point, publicly a property is an NSArray *. Privately, it’s
NSMutableArray *. Right now I want to do this, but can’t due to an error on the
property in the class extension:

.h:

#import <Foundation/Foundation.h>

@interface BOOMObject : NSObject
@property (nonatomic, readonly) NSArray *items;
@end


.m:

#import "BOOMObject.h"

@interface BOOMObject ()
@property (nonatomic, readonly) NSMutableArray *items;
@end

@implementation BOOMObject

-(void)addItem:(id)item {
    [self.items addObject:item];
}

@end


error: illegal redeclaration of property in class extension 'BOOMObject'
(attribute must be 'readwrite', while its primary must be 'readonly')


The identical problem occurs when both properties are readwrite.


Even more unfortunate is what happens when you have a public readonly property
and a private readwrite one of the subtype, and try to call mutate the
(mutable!) array with e.g. [self.items addObject:…]:


error: no visible @interface for 'NSArray' declares the selector 'addObject:'


Same thing happens with direct ivar access, so you effectively cannot do this
at all.


I think all three of these (public & private readonly, public & private
readwrite, and public readonly, private readwrite) are legitimate patterns that
I would like to see explicitly supported as-is. Thus far my workarounds are:

1. declare a private NSMutableArray *mutableItems property, using it for all
mutations of the array, and implement -items to simply return self.mutableItems
(or if I’m feeling paranoid, [self.mutableItems copy]).

2. declare the ivar explicitly as NSMutableArray *_items and use it directly
(ick) when mutating.

3. do as #2, but declare a private readonly mutableItems property which is
implemented explicitly (not synthesized) to return _items, and do mutations of
the array through it. This is more or less the inverse of #1.


Since there are already rules for redeclaring a property in a class extension,
I would request that these be extended to allow subtypes to be used internally.
By subtypes I mean:

- if the public type is an object type of a specific class, the private type
can be that class or any subclass of it
- if the public type is an object type of a specific class, the private type
can be a specialization of the public class by one or more protocols, e.g.:

@property (readonly) Foo *foo; // public
@property (readonly) Foo<Bar> *foo; // private

- ditto, but a specialization of a subclass of the public class by one or more
protocols:

@property (readonly) SubFoo<Bar> *foo; // private

- ditto for public protocols and private protocols which inherit from them,
whether the public type is id or a specific class:

@protocol SubBar <Bar>
…
@end

@property (readonly) Foo<Bar> *foo; // public
@property (readonly) SubFoo<SubBar> *foo; // private

- if the public type is id, any more specific object type can be used privately


Crucially, uses of the accessor within any scope that has visibility on the
property in the class extension should get the type of the class extension’s
declaration of the property. I.e. if I make a FooSubclass.h file that has the
class extension in it, my subclasses should see the “real” type, not the public
(and more restrictive) type.

Gravy would be allowing multiple such declarations. Public interface might
specify NSSet, subclass-visible class extension might specify NSMutableSet,
private class extension might specify NSCountedSet.


Does this make sense? Is there any consensus that it’s a reasonable thing to
allow?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20130730/c39f4e15/attachment.html>


More information about the llvm-bugs mailing list