Embedded Swift

We wouldn't change anything about String on existing platforms; on embedded platforms, there would just be a subset of its existing functionality. Being able to still use String and its views in embedded modes would have the benefit of existing code being easier to port. [UInt8] also isn't and probably shouldn't be ExpressibleByStringLiteral or -Interpolation, but String can still implement both of those on embedded platforms.

5 Likes

Weak specifically, or unowned as well? Unowned are easier to do, even if they are unsupported (I don't know if they are or aren't) – store the unsafeBitCast(reference, to: Int.self) integers in the dictionary and do the reverse unsafeBitCast(int, to: RefType.self) when querying the dictionary.

Don’t Swift objects maintain two refcounts, one for strong and one for weak/unowned? This wouldn’t touch the unowned refcount.

1 Like

As soon as this is done – people who had those will throw away their custom String implementation and use the standard library one.

I don't have hard numbers but it feels that in the majority of cases of embedded platforms the actually used API surface is quite small: count, ==, hash, possibly <, init ascii/utf8 strings from data, convert them back to data, converting numbers to strings, and back and coding/decoding strings which are part of JSON. Alphabetically comparing strings would be probably the most complicated but those who could tolerate using ASCII-only strings would be happy using a simple < instead (which would not give correct results for unicode strings).

Three, actually. The strong and unowned recounts are in the object, the weak refcount is outside it.

@David_Smith Can you please share what is the max possible number of strong / weak / unowned references? I mean are they limited to UInt16 / 32 / 64?

== is one of the hard ones, unfortunately! "Full" Swift ensures that "{E WITH ACUTE ACCENT}" is equal to "{E}{COMBINING ACUTE ACCENT}". So we'd need to pick one of the following:

  1. Embedded Swift includes the subset of Unicode tables necessary for canonical equality (if you use String)
  2. Embedded Swift defines String equality differently than "Full" Swift
  3. Embedded Swift does not make String Equatable (which means it wouldn't be Hashable either)
6 Likes

It will fall back to external storage above a platform dependent threshold, although there are cases where this hasn’t worked correctly before ( see commit history for this file swift/stdlib/public/SwiftShims/swift/shims/RefCount.h at main · apple/swift · GitHub )

3 Likes

Right. Of course, we could still add those conformances to String.UTF8View (and maybe the other views) with the explicit understanding that they're based on the code unit sequence. I don't know if there are good arguments against doing that, though.

10 Likes

@shantini has a PR for that: [SE-NNNN] Add Equatable and Hashable Conformance to String views by pershanti · Pull Request #1637 · apple/swift-evolution · GitHub

As far as I know we haven't landed it solely due to concerns about retroactive conformance conflicts causing compatibility breaks, it would be great to sort out how to do it.

4 Likes

I agree, that would be useful even on desktop Swift, where oftentimes code unit comparison is all you want or need for performance or correctness needs, and it would be a nice way of portably expressing code unit comparison across desktop and embedded Swift.

10 Likes

There's also a 4 for completeness:

  1. Embedded Swift supports ASCII strings only.

I'd say #4 or #2. Option #3 would be too restrictive. Not sure about #1.

2 Likes

I’d probably get a lot of mileage out of just UInt8/ascii strings alone, so would welcome option 4.

I’m not sure if this has already been suggested, but perhaps an AsciiString type could be added to Swift so it is available on all platforms. I expect this would be generally useful for many people.

Then embedded Swift could say something like, “String is not available, try using AsciiString instead.”

11 Likes

+1 thinking full Swift String capabilities aren't needed in Swift Embedded, but not 100% sure what the future holds.

As general rule if find myself trying to do any kind of real work with Strings on an embedded device that's typically a sign I've probably made an architecture mistake somewhere. But now we have a world with tiny little screens that are super cheap and everywhere. And screens seem to attract emojis like dust on a cat's whiskers.

FWIW, whole new type or mask on same-named-type is one aspect the MicroPython vs CircuitPython philosophical fork. (both excellent projects)

Swift is very different from Python, but it still might be interesting to look at some of the decisions they've made.

CP Examples for anyone wandering into this thread whose never worked with human interface and text on a micrcontroller or to see the compromises CircuitPython made:

5 Likes

That‘s a very good plan!

Or:

typealias String = AsciiString

I wonder if that's really wise, or if it would be a bit like defining:

typealias Double = Float

or

typealias Int64 = Int16
6 Likes

This would be a more reasonable parallel:

struct Int64 {
    var components: (Int32, Int32)
    // a limited subset of Int64 API follows.
}

Right, anything embedded that's of any real interest will need to address world-wide markets and their genuine UI demands. ASCII is good enough for debugging and AdventOfCode :) Option #1 looks attractive.