# StrictValueType protocol

**URL:** <https://forums.swift.org/t/strictvaluetype-protocol/63229>\
**Category:** Pitches\
**Created:** [February 20, 2023, 2:55pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229 "2023-02-20T14:55:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![henrikdvn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/henrikdvn/32/28646_2.png) [@henrikdvn](https://forums.swift.org/u/henrikdvn)\
**Post date:** [February 20, 2023, 2:55pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/1 "2023-02-20T14:55:09Z")

</div>

I propose a protocol named **StrictValueType** which requires that conforming types are value-types in the traditional sense, i.e. types with fixed memory footprints that can be determined compile-time. With this protocol it will be possible to define types that can be:

- stack allocated,
- managed without ARC and
- passed as parameters to low level C functions

using standard Swift protocols and generics.

Conforming types should include C value-types, primitive Swift types and Swift/C structs with conforming members. Reference-types and simulated value-types such as String, Array etc. should not be included. Neither should structs containing such types.

A reasonably safe, stack allocatable, no-ARC manageable array could be defined like this:

```
struct StrictValueArray<Storage: StrictValueType, Element: StrictValueType> {

	private var storage = Storage()

	var capacity: Int {
		return MemoryLayout<Storage>.stride / MemoryLayout<Element>.stride
	}
		
	subscript(index: Int) -> Element {
		get {
			assert(index >= 0 && index < capacity, "Index out of range")
			return withUnsafeBytes(of: storage) { (rawPtr) in
				return rawPtr.baseAddress!.assumingMemoryBound(to: Element.self)[index]
			}
		}
		set(newValue) {
			assert(index >= 0 && index < capacity, "Index out of range")
			withUnsafeMutableBytes(of: &storage) { (rawPtr) in
				rawPtr.baseAddress!.assumingMemoryBound(to: Element.self)[index] = newValue
			}
		}
	}
}

```

A string-convertible type with memory footprint equivalent to the C-type "char var[n]" could be defined like this:

```
struct StrictValueString<Storage: StrictValueType> {

	private var storage = Storage()

	var capacity: Int {
		return MemoryLayout<Storage>.stride
	}
	
	var stringValue: String {
		get {
			return withUnsafeBytes(of: storage) { (rawPtr) in
				return String(cString: rawPtr.baseAddress!.assumingMemoryBound(to: CChar.self))
			}
		}
		set(newValue) {
			assert(newValue.count < capacity, "String value overflow")
			strcpy(&storage, "\(newValue)")
		}
	}
}

```

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [February 20, 2023, 3:53pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/2 "2023-02-20T15:53:38Z")

</div>

Your proposed `StrictValueType` [already exists as `_Trivial`](https://github.com/apple/swift/blob/main/docs/archive/Generics.rst#specialization).

---

<div class="post-metadata">

**Author:** ![henrikdvn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/henrikdvn/32/28646_2.png) [@henrikdvn](https://forums.swift.org/u/henrikdvn)\
**Post date:** [February 20, 2023, 5:03pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/3 "2023-02-20T17:03:20Z")

</div>

Just tested **\_Trivial**. String and class types were accepted without complaints.

\_Trivial is not a protocol. According to the documentation it is a constraint that can be applied within a @\_specialize function which "currently acts as a hint to the optimizer".

I guess \_Trivial may (in principle) do the job at some point in the future, but a protocol would a better option in my opinion.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 20, 2023, 5:22pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/4 "2023-02-20T17:22:46Z")

</div>

`_Trivial` is, as you noted, currently an internal layout constraint that's only used by specialization. But we do plan to expose it as a `BitwiseCopyable` generic constraint that can be used on generic parameters and protocol requirements soon.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [February 20, 2023, 5:24pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/5 "2023-02-20T17:24:34Z")

</div>

> [@henrikdvn](#):
>
> I propose a protocol named **StrictValueType** which requires that conforming types are value-types in the traditional sense, i.e. types with fixed memory footprints that can be determined compile-time.

I welcome this proposal. Not sure if the name is the bestest.  
Is this the same as "POD" conceptually or will there be some differences between the two?

> [@henrikdvn](#):
>
> Conforming types should include C value-types, primitive Swift types and Swift/C structs with conforming members.

Let me clarify: this is a pseudo protocol, and the conformances would be automatic, right? No way to opt-in, and perhaps no need to have a way to opt-out either.

> [@henrikdvn](#):
>
> Reference-types and simulated value-types such as String, Array etc. should not be included. Neither should structs containing such types.

💯

I understand that what you outlined is a sketch, a few suggestions though:

- A small typo in capacity – should be "size" in the numerator ("stride" in denominator is good).
- I'd also change "asserts" to "preconditions" so release builds are checked as well.
- The setter in stringValue implementation looks incorrect. Try testing it with emoticons or just non-ascii symbols, etc.

> [@henrikdvn](#):
>
> Just tested **\_Trivial**.

How do you guys use \_Trivial? It says "Error: Cannot find type '\_Trivial' in scope" for me.

> [@henrikdvn](#):
>
> String and class types were accepted without complaints.

This is not good then.. StrictValueType should neither accept classes nor "structs with classes", nor "structs with structs with classes", etc.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [February 20, 2023, 5:36pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/6 "2023-02-20T17:36:52Z")

</div>

> [@tera](#):
>
> This is not good then.. StrictValueType should neither accept classes nor "structs with classes", nor "structs with structs with classes", etc.

What if the class is move-only? Then you can bitwise-copy the struct as long as you destroy the original.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 20, 2023, 5:42pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/7 "2023-02-20T17:42:48Z")

</div>

I think that question is a good example of why "BitwiseCopyable" or something like it is a more descriptive name than traditional C++ terms like "trivial" or "POD", or other more indirect terms. If a type contains move-only things, the container also can't be copied, so it wouldn't be bitwise copyable.

---

<div class="post-metadata">

**Author:** ![ksluder](https://avatars.discourse-cdn.com/v4/letter/k/eada6e/32.png) [@ksluder](https://forums.swift.org/u/ksluder)\
**Post date:** [February 20, 2023, 5:44pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/8 "2023-02-20T17:44:18Z")

</div>

But I can still imagine wanting to bitwise copy a struct with a move-only class reference in it (or a move-only struct with a known-unique class reference) if I were implementing a custom allocator.

I guess these are both possible to implement with unsafe memory operations and a move-only constraint, rather than a bitwise-copyable constraint.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [February 20, 2023, 5:46pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/9 "2023-02-20T17:46:44Z")

</div>

> [@Joe\_Groff](#):
>
> I think that question is a good example of why "BitwiseCopyable" or something like it is a more descriptive name than traditional C++ terms like "trivial" or "POD", or other more indirect terms. If a type contains move-only things, the container also can't be copied, so it wouldn't be bitwise copyable.

I don't know if the original StrictValueType had this property or not, but I believe it is important to have a notion of types that could be fwritten and recreated with fread after app relaunch - obviously that won't work with references. I.e. this is much stricter than just "bitwise copyable".

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 20, 2023, 6:02pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/10 "2023-02-20T18:02:29Z")

</div>

> [@ksluder](#):
>
> But I can still imagine wanting to bitwise copy a struct with a move-only class reference in it (or a move-only struct with a known-unique class reference) if I were implementing a custom allocator.

That sounds more like a bitwise move to me, since copying the bits of the value with the reference necessarily needs to transfer ownership of that reference to the value in the new place.

> [@tera](#):
>
> I don't know if the original StrictValueType had this property or not, but I believe it is important to have a notion of types that could be fwritten and recreated with fread after app relaunch - obviously that won't work with references. I.e. this is much stricter than just "bitwise copyable".

Yeah, that would have to be a stricter constraint, since things like pointers, metatypes, and other process-specific values can be bitwise-copied within the context of a process, but aren't serializable.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [February 20, 2023, 6:03pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/11 "2023-02-20T18:03:09Z")

</div>

> [@tera](#):
>
> the conformances would be automatic, right? No way to opt-in, and perhaps no need to have a way to opt-out either.

Perhaps a bit like Sendable: automatic for internal types, but explicit for public types as to prevent accidentally guaranteeing something it shouldn’t.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [February 20, 2023, 7:33pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/12 "2023-02-20T19:33:29Z")

</div>

> [@bbrk24](#):
>
> Perhaps a bit like Sendable: automatic for internal types, but explicit for public types as to prevent accidentally guaranteeing something it shouldn’t.

This deserves an example. E.g. you are making your own type like `CGPoint` and don't want it to be `StrictValueType` (why?).

> [@Joe\_Groff](#):
>
> Yeah, that would have to be a stricter constraint, since things like pointers, metatypes, and other process-specific values can be bitwise-copied within the context of a process, but aren't serializable.

On the naming front, "serialisable" to me suggests "an ability to serialise / deserialise", e.g. it could be achieved with some "var serialiseToBytes: Data; init(serialisedData: Data)" requirement, or the same way as Codable is done – in these regards using the name like "Serialisable" instead of "POD" would be quite confusing.

The term [Passive data structure (PDS)](https://en.wikipedia.org/wiki/Passive_data_structure) is also used in the industry.

To sum up, we are discussing a few quite different things here:

1. POD/PDS values (those can be recreated as "copies" from bits in a different process).
2. values that can be recreated as copies from bits in the same process only.
3. a value that can be recreated as a unique copy from bits in the same process (original value is destroyed). Attempt to create a second copy from the same bits should fail (somehow)_, or successfully create a new unique copy with the previously unique copy destroyed the moment the new unique copy is created (Edited)_.

Coming from C++ the 1st option is the simplest to grasp.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [February 20, 2023, 9:07pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/13 "2023-02-20T21:07:09Z")

</div>

> [@tera](#):
>
> E.g. you are making your own type like `CGPoint` and don't want it to be `StrictValueType` (why?).

Let me take an example from a library I've worked on:

```swift
public struct Scope: Equatable {
    internal let value: UnderlyingType
    
    public static let transient = Scope(value: .transient)
    public static let singleton = Scope(value: .singleton)
    public static let weak = Scope(value: .weak)
    
    internal enum UnderlyingType: Equatable {
        case transient
        case singleton
        case weak
    }
}

```

Here, we've intentionally hidden the underlying enum. Only a wrapper struct is exposed. If, in the future, I add a new case to the enum:

```swift
case foo(String)

```

Suddenly the wrapper struct is no longer `StrictValueType`, and it could be a breaking change to clients.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [February 20, 2023, 11:33pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/14 "2023-02-20T23:33:17Z")

</div>

Note that we have a similar simple use case already:

Library defines:

```
public enum E { case e }

```

Client starts using it:

```swift
struct S: Equatable { var e: E }

```

then library adds a new enum constant:

```swift
public enum E {
    case e
    case n(NSObject)
}

```

breaking the client code as "E" is no longer Equatable.

Note that we don't have an opt-out from the automatic equatable conformance now. Perhaps there are other similar cases.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [February 21, 2023, 12:37am UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/15 "2023-02-21T00:37:42Z")

</div>

IMO the implicit conformance of enums to `Equatable` is bad and I would love to see it removed if there’s a way to make the (likely significant) source break manageable. I certainly wouldn’t to see it used as precedent to introduce _additional_ implicit conformances. (Though as with `Sendable` it’s not really an issue for non-public types.)

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [February 21, 2023, 1:03am UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/16 "2023-02-21T01:03:25Z")

</div>

Note that for _public_ enums, adding a new case is already source-breaking. [That's why we made that enum internal.](https://github.com/Tiny-Home-Consulting/Dependiject/issues/67)

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [February 21, 2023, 2:07am UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/17 "2023-02-21T02:07:35Z")

</div>

> [@bbrk24](#):
>
> Perhaps a bit like Sendable: automatic for internal types, but explicit for public types as to prevent accidentally guaranteeing something it shouldn’t.

This sounds like a reasonable compromise.

How does this mechanism work exactly? For example this compiles:

```swift
internal class S1 {}
public class S2 {}

func foo() {
    let s1: Sendable = S1()
    let s2: Sendable = S2() // compiles just fine
}

```

Shouldn't S2 require an explicit "Sendable" marker here?

---

<div class="post-metadata">

**Author:** ![henrikdvn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/henrikdvn/32/28646_2.png) [@henrikdvn](https://forums.swift.org/u/henrikdvn)\
**Post date:** [February 21, 2023, 11:56am UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/18 "2023-02-21T11:56:29Z")

</div>

> [@Joe\_Groff](#):
>
> `_Trivial` is, as you noted, currently an internal layout constraint that's only used by specialization. But we do plan to expose it as a `BitwiseCopyable` generic constraint that can be used on generic parameters and protocol requirements soon.

Ok. I guess that will do the trick. Good news for grumpy old C programmers like me 🙂

> [@tera](#):
>
> A small typo in capacity – should be "size" in the numerator ("stride" in denominator is good).

Yes. I now realise that "stride" in the numerator only works when `Storage` is a homogenous tuple consisting of `Element` values.

So: any chance of getting a `HomogenousTuple` constraint any time soon?

Something like this would of course also be useful:

```
HomogenousTuple.init(repeating: Element, count: Int)

```

Should be `BitwiseCopyable` if `Element` is `BitwiseCopyable`

---

<div class="post-metadata">

**Author:** ![henrikdvn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/henrikdvn/32/28646_2.png) [@henrikdvn](https://forums.swift.org/u/henrikdvn)\
**Post date:** [February 21, 2023, 2:44pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/19 "2023-02-21T14:44:40Z")

</div>

> [@tera](#):
>
> Let me clarify: this is a pseudo protocol, and the conformances would be automatic, right? No way to opt-in, and perhaps no need to have a way to opt-out either.

I suggest opt-in for custom structs and automatic for primitive values. Not sure if it is possible to enforce protocol conformance for C types, but it would certainly be useful.

> [@tera](#):
>
> A small typo in capacity – should be "size" in the numerator ("stride" in denominator is good)

Agreed. But, as noted above, I think "stride" in the `StrictValueArray` struct should be ok when `Storage` is a homogenous tuple consisting of `Element` values. StrictValueString capacity, however, should definitely be based on "size".

> [@tera](#):
>
> - I'd also change "asserts" to "preconditions" so release builds are checked as well.

Point taken 🙂

> [@tera](#):
>
> The setter in stringValue implementation looks incorrect. Try testing it with emoticons or just non-ascii symbols, etc.

Think the setter works, but the size calculation is wrong. Should be changed to

```
newValue.lengthOfBytes(using: .utf8)

```

> [@tera](#):
>
> How do you guys use \_Trivial? It says "Error: Cannot find type '\_Trivial' in scope" for me.

Here is my test code:

```
class Product {
	var name: String

	init(name: String) {
		self.name = name
	}
}

struct TrivialStorage<Storage, Element> {

	var storage: Storage
	@_specialize(where Storage: _Trivial, Element: _Trivial)

	init(storage: Storage) {
		self.storage = storage
	}
}

var products = TrivialStorage<Array<Product>, Product>(storage: [Product(name: "Chair")])

print("\(products.storage[0].name)")
// Chair

```

---

<div class="post-metadata">

**Author:** ![henrikdvn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/henrikdvn/32/28646_2.png) [@henrikdvn](https://forums.swift.org/u/henrikdvn)\
**Post date:** [February 21, 2023, 3:56pm UTC](https://forums.swift.org/t/strictvaluetype-protocol/63229/20 "2023-02-21T15:56:12Z")

</div>

I fear this is just wishfull thinking, but given a `BitwiseCopyable` protocol which corresponds to \_Trivial and a `HomogenousTuple` protocol, it would be possible to define a safe and storage efficient generic BitwiseCopyableArray like this:

```
// Type "without any reference counted properties"
protocol BitwiseCopyable {
}

// Tuple containing only Element values
protocol HomogenousTuple {
	associatedtype Element
	init()
}

struct BitwiseCopyableArray<Storage: HomogenousTuple, Element: BitwiseCopyable> where Storage.Element == Element {
	
	internal var storage = Storage()
	
	var capacity: Int {
		return MemoryLayout<Storage>.stride / MemoryLayout<Element>.stride
	}
	
	subscript(index: Int) -> Element {
		get {
			precondition(index >= 0 && index < capacity, "Index out of range")
			return withUnsafeBytes(of: storage) { (rawPtr) in
				return rawPtr.baseAddress!.assumingMemoryBound(to: Element.self)[index]
			}
		}
		set(newValue) {
			precondition(index >= 0 && index < capacity, "Index out of range")
			withUnsafeMutableBytes(of: &storage) { (rawPtr) in
				rawPtr.baseAddress!.assumingMemoryBound(to: Element.self)[index] = newValue
			}
		}
	}
}

```

[Next page](https://forums.swift.org/t/strictvaluetype-protocol/63229.md?page=2)
