Or, more specifically, (readonly, retain) enables a pattern like this:
Foo.h:
@interface StuffHolder:NSObject
@property(readonly, retain) MyStuff *stuff;
@end
Foo.m:
@interface StuffHolder()
@property(readwrite, retain) MyStuff *stuff;
@end
@implementation StuffHolder
@synthesize stuff;
@end
The end result is a property that is publicly readonly while being readwrite within the implementation and for whom both setter and getter are synthesized automatically by the compiler.
A warning could be generated in the case of no (readwrite, retain) override in the class extension -- something akin to statement without an effect
-- but it would be more confusing than beneficial. There are also a whole slew of different edge cases across the combinations that would equally warrant a warning, but don't really indicate an actual problem. The decision was made to largely accept the various patterns without complaint for simplicity's sake (since they aren't correctness issues).