SE-0349: Unaligned loads and stores from raw memory

Hello, Swift community.

The review of SE-0349: Unaligned loads and stores from raw memory begins now and runs through April 12th, 2022.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager. When emailing the review manager directly, please keep the proposal link at the top of the message.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md

Thank you,

John McCall
Review Manager

21 Likes

+1 This looks good to me, we've needed unaligned loads for a while, and I don't see anything wrong with this API for it. I do have a minor question though, is POD the same as a trivial type or is it a stronger constraint?

Also, what's the blocker on having a user accessible way to constrain a type to be trivial/POD?

From Swift's point of view, they are the same. Compiler folk tend to see them slightly differently. Personally, I think that using the word "trivial" here is a misnomer, and I would prefer we found a better name. These types are neither uninteresting nor unimportant! (I'll step off the soapbox now.)

The blocker on a marker protocol for POD types is the compiler work it requires.

For the record, both terms come from C++:

The last is basically how "trivial" is used by compiler people for Swift types; we don't privilege no-arg constructors in the language, so there's not much reason to prefer "trivially copyable" to "trivial". "Bitwise-copyable types" would be a reasonable bland term for what these pointer APIs require, at least until we start talking about move-only types…but it really is a concept that deserves A Name and Documentation and Some Language Support, so maybe that's too bland.

11 Likes

The proposed API is exactly what I expected to exist when I needed this functionality in the past, so this seems like an easy +1.

I'm a little surprised that the marker protocol is enough work to justify delaying it, but as long as there's zero risk of being unable to add that later due to ABI concerns it isn't a big enough problem to block the feature.

1 Like

What is your evaluation of the proposal?

Yes please. We've needed this for a long time; it's possible to work around, but quite annoying to do so.

Is the problem being addressed significant enough to warrant a change to Swift?

Absolutely.

Does this proposal fit well with the feel and direction of Swift?

Yes.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

There are surprisingly few languages with "similar features" despite obvious utility for low-level programming. C and C++ have either memcpy, intrinsics, or compiler-specific features (all of which I have used heavily, and all of which are distinctly worse than what Guillaume has proposed).

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

In-depth study.

7 Likes

“Trivial” may be worth keeping as a term but I think we should avoid the term POD. People coming from Java sometimes confuse it with POJO and may get the impression from people alternating between POD and trivial that String is trivial.

7 Likes

Note: I improved the paragraph in "Proposed Solution" relating to the proposed changes to (of:toByteOffset:as:).

1 Like

+1 looks like a great improvement for folks who need this type of low level API. It seems that lately these type of low level API have been brought up for review which is exciting if we want Swift to be used more for low level performant API.

I do want to highlight this comment from the API.

This function only supports loading trivial types, and will trap if this precondition is not met.

Traps:

The Swift standard library loves traps but API that trap it’s not easily discoverable. I wonder if we can have a more standard way to add a documentation “traps” section similar to param or returns so that consumers can easily parse invariants being checked and on which bucks configs. In addition, any trapping API should include a non trapping way to check if call would trap or not. For example, an an array I can avoid the index out of range trap by checking my index range and that index range check doesn’t trap ( if the user math logic is correct :smile_cat:)

trivial types:

Is there a compile time check that can be added to the type today so folks can validate if a type is trivial? Or is there a reflection/runtime check for folks to use to avoid tripping the precondition? I do see that in the alternatives considered we have a market protocol but I am thinking more of an attribute added to the type that would do this check without requiring a marker protocol.

2 Likes

Some sub-protocols of Codable include precondition rubrics in their doc-comments, but unfortunately those just appears in the "Discussion" section. It's better than nothing, though: I think I'll adopt that. At least it would call it out more prominently than just another sentence in the description. In any event if a trap occurs without a reasonable message, that's a bug.

I do like the idea of having a straightforward function that would tell you whether an index is valid at runtime. That might have more legs than the various non-trapping subscript pitches that have floundered over the years.

That would be the marker protocol, and that would be the ideal outcome. Making that a prerequisite for this functionality would delay it even longer, when it's already been delayed for too long. An attribute would not expedite anything, I believe.

The stdlib has for a long while exposed a public underscored function that would help you ascertain whether a type qualifies: func _isPOD<T>(_ type: T.Type) -> Bool.

4 Likes

The Core Team has decided to accept SE-0349.

Thank you all for participating in this review.

John McCall
Review Manager

3 Likes