Why unable to debug "Step Into" `Decimal(string:locale:)`?

I'm trying to figure out why Decimal(string: "0.3") doesn't use the system default locale decimal separator as it should. I set a breakpoint at:

let _ = Decimal(string: "0.3")

when click "Step Into", the execution just go to the next line. Why is this? How can I step into Foundation source code?

Debug build or release build? I think that in a debug build you should be able to step into the initialiser. You won’t be able to see the source code, it’ll just show you the disassembly. It’s just a side-effect of working with Apple’s closed source libraries.

If it is a debug build and you’re not able to step into, maybe try setting the breakpoint a few lines earlier? Ive had issues in the past when setting a breakpoint on the exact line I want. Sometimes it seems that the breakpoint is too late and things like step into dont work.

No, you can't generally step into precompiled libraries, as there is no source code associated with its execution. If you build Foundation from source and linked that into your executable you might be able to, but only Apple can really do that, on Apple platforms at least. On Linux it may be theoretically possible since you can use the open source version and build it yourself, but it doesn't really help since the implementations are different between platforms.

If you really want to inspect the implementation your best best is a dissembler like Hopper, which can analyze the binary and make it somewhat readable.

It's debug build. I did try setting breakpoint a few lines ahead but still cannot step into that call. @Jon_Shier said "can't generally step into precompiled libraries."

You should definitely be able to step into the disassembly, because that’s always available even when source code isn’t. Maybe Xcode just doesn’t want to step into functions which don’t have source code available. It’s probably a setting somewhere because I’ve done that before.

But either way, the disassembly is probably not what you’re looking for I guess, because you need to know a bit of assembly to figure out what the disassembly means.

1 Like

You should definitely be able to step into the disassembly

Indeed.

To step into the disassembly you’ll need to use the inst variants of the underlying LLDB commands. In the Xcode GUI you can get this by holding down the control key while pressing the Step button. You’ll need to click multiple times to get past the instructions that set up the call in your source function.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

… who supports Apple’s closed source frameworks and thus does a lot of assembly-level debugging (-:

2 Likes

Are you testing this on an Apple platform, or a different platform like Linux or Windows?

The source code you linked is only used on non-Apple platforms. Apple uses a private implementation of Foundation on its platforms. However, much of Swift layer on top of the private Foundation was part of the swift repo prior to release 5.5, including the implementation of Decimal(string:locale:):

    public init?(string: __shared String, locale: __shared Locale? = nil) {
        let scan = Scanner(string: string)
        var theDecimal = Decimal()
        scan.locale = locale
        if !scan.scanDecimal(&theDecimal) {
            return nil
        }
        self = theDecimal
    }

Here we can see that, if you don't pass a Locale (or if you pass nil), it sets the scanner's locale to nil. The NSScanner documentation says

A scanner with no locale set uses non-localized values.

That is why your call to Decimal.init?(string:) always uses . as the decimal separator.

I'm on iOS. So the behavior match Apple's NSScanner doc. :+1::pray:

However, on non-Apple platform it works differently for locale == nil, it uses the system default locale:

Scanner.scanDecimal(...)

So to be portable across platforms, must specify en_US for Decimal(string:locale) so "." decimal separator is used always. I wonder: is the non-Apple version buggy since it doesn't match Apple's version base on eye balling at the source? If this is a bug, who should know about this?

Thanks for solving my mystery!

I've heard the Foundation overlays are now part of the swift-corelibs-foundation repo but I haven't found them.

Not matching the Apple platform behavior is generally a bug in swift-corelibs-foundation, so reporting a bug would be a good idea.

Thanks for the heads up. I found them here:

https://github.com/apple/swift-corelibs-foundation/tree/eec4b26deee34edb7664ddd9c1222492a399d122/Darwin/Foundation-swiftoverlay