objective c - Why doesn't a generic NSDictionary warn me about incorrectly-typed key inserts/assignments? -


why don't following nsdictionary/nsmutabledictionary calls produce error or warning?

i expect error here because rhs nsdictionary literal doesn't match generic types of nsdictionary lhs local variable.

nsdictionary<nsstring *, nsnumber *> *foo = @{ @(42) : @"foo" }; 

i expect error here because key type doesn't match nsmutabledictionary's key generic type:

nsmutabledictionary<nsstring *, nsnumber *> *foo = [nsmutabledictionary new]; // neither of these calls produces error. :( foo[@(42)] = @(42); [foo setobject:@(42) forkey:@(42)]; 

i see error when try assign improperly-typed value, know generics errors working somewhat:

nsmutabledictionary<nsstring *, nsnumber *> *foo = [nsmutabledictionary new]; foo[@"foo"] = @"bar"; 

causes following warning:

foo.m:81:16: incompatible pointer types sending 'nsstring *' parameter of type 'nsnumber * _nullable' 

why don't literal assignment or improperly-typed keys cause warnings/errors?

i filed radar.

seems limitation/bug of compiler, caused definition of setobject:forkeyedsubscript: method:

- (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype <nscopying>)key; 

the protocol conforming requirement somehow hides type requirement keytype. if <nscopying> not present, compiler makes keytype check , warns you.

to confirm this, played code, here results:

@interface mydictionary<keytype, objecttype>: nsobject     - (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype <nscopying>)key; @end  ...  mydictionary<nsnumber*, nsnumber*>* dict = [[mydictionary alloc] init]; uibutton *button = [[uibutton alloc] initwithframe:cgrectzero]; dict[@"98"] = @14; // no warnings dict[button] = @14; //warning: sending 'uibutton *' parameter of incompatible type 'id<nscopying>' 

the above code has same behaviour nsmutabledictionary. however, if remove <nscopying> protocol conformance restriction keytype, compiler gives appropriate warning:

@interface mydictionary<keytype, objecttype>: nsobject - (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype)key; @end  ...  mydictionary<nsnumber*, nsnumber*>* dict = [[mydictionary alloc] init]; dict[@"98"] = @14; // warning: incompatible pointer types sending 'nsstring *' parameter of type 'nsnumber *' 

note. default you'll warnings object types mismatch, if want receive errors, can either enable treat warnings errors build setting, or treat incompatible pointer type warnings errors one.


Comments

Popular posts from this blog

SVG stroke-linecap doesn't work for circles in Firefox? -

routes - Laravel 4 Wildcard Routing to Different Controllers -

cross browser - XSLT namespace-alias Not Working in Firefox or Chrome -