Xcode 15 RC bug with interpreting objective-c literal @-1.

Not even sure if it started with Xcode 15 RC, but that's when I found it. I believe that in Xcode 14 and all before it objective-c literal @-1 was interpreted correctly as NSNumber -1. Not with Xcode 15 RC, when I use @-1 in the objective-c array as:

        _types = @{
            @-2:[[CircleWaypointType alloc] init],
            @-1:[[PolygonPointWaypointType alloc] init], 

@-2 is interpreted correctly, but @-1 is not:

(lldb) po _types
{
    18446744073709551615 = "<PolygonPointWaypointType: 0x2802fa840>";
    "-2" = "<CircleWaypointType: 0x2802fa7c0>";
}

The array type is NSDictionary<NSNumber*, WaypointType*> *types, so the interpreter/compiler should not have a problem with the type of the literal, I think.

Reported to Apple under FB13181573.

It's possible that this only happens when @-1 is used in the array, I have not had time to explore/test more. Reporting here, so you would not be hit by this pretty obscure thing.

Workaround was obvious, using [NSNumber numberWithInt:-1] works as intended.

Replies

Well that’s weird. Your test case is working correctly for me here in Xcode 15.0 (15A240d) on a Mac with M1 Max.

Does the behavior change if you format the literal as @(-1) with parentheses?

Can you format the key via some code (like a number formatter) to confirm the issue is really the compiler, vs just an issue in the debugger?

That value 18446744073709551615 happens to be 2^64-1, the same bit pattern as -1 in a 64-bit signed integer. Maybe that’s a clue.

Hi Scott,

I created a unit test now as well, like this:

/// https://feedbackassistant.apple.com/feedback/13181573
- (void)testTypes {
    
    NSDictionary<NSNumber*, WaypointType*> *types = @{
        [NSNumber numberWithInt:-2]:[[CircleWaypointType alloc] init],
        [NSNumber numberWithInt:-1]:[[PolygonPointWaypointType alloc] init],


        @0:[[OtherWaypointType alloc] init],
        @1: [[FixedCameraWaypointType alloc] init],
    };

    NSLog(@"Types: %@", [types description]);
    
    for (NSNumber *key in [types allKeys])
    {
        NSLog(@"1. Key: %@", key);
    }
    
    types = @{
        //https://feedbackassistant.apple.com/feedback/13181573
        @-2:[[CircleWaypointType alloc] init],
        @-1:[[PolygonPointWaypointType alloc] init],
        @0:[[OtherWaypointType alloc] init],
        @1: [[FixedCameraWaypointType alloc] init],
    };
    
    for (NSNumber *key in [types allKeys])
    {
        NSLog(@"2. Key : %@", key);
    }
}

And output for @-1 and [NSNumber numberWithInt:-1] is the same in the unit test:

2023-09-18 17:16:48.788685+0200 speedometer[84584:1342510] 1. Key: -1

2023-09-18 17:16:48.789099+0200 speedometer[84584:1342510] 2. Key : -1

I tried then to run the app itself in the simulator (was running on a iOS 16 and 17 devices before). When ran as the app in iOS 17 simulator @-1 and @(-1) turns into 18446744073709551615 in the dictionary, same as it is doing it on iOS 16-17 devices.

Xcode is Version 15.0 (15A240d)

Looks like that unit test doesn't reveal the issue, compiling/running as the app does. Either on simulator or the real device.

Thank you for the suggestions! Stan.

P.S. Here it is in the debugger preview while running the app in the simulator (same on the real device):

It doesn't match -1 for the objectForKey when NSNumber is -1, so it should be turning into this value 18446744073709551615, I think this is not just a debugger misrepresentation.

P.P.S. Also strange how @1 is of (int) type, but @6 is (long), why it would be like this? Looks like some unexpected type random conversion liberty by a compiler (or debugger in this case?).