[Pitch] Renaming sizeof, sizeofValue, strideof, strideofValue

Yes but, if they weren’t functions now, what would be the best design?

How many Swift developers will be using this functionality? Less than 1%? I trust Dave’s judgement because he is in that small group.

···

On 2 Jun 2016, at 3:27 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com <mailto:pgwsmith@gmail.com>> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

Well, as I understand it, it's not actually possible to write your own
type(of:), so we're going from a "magic" property to a "magic" function at
least for now.

I'm most alarmed that one implication of the MemoryLayout proposal is loss
of the `ofValue` family of functions. These functions don't fit with the
design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`?
But the response seems to be that these functions don't seem necessary at
all and should be removed. "I don't see a use for it" is an insufficient
justification for a feature removal. Looking to other languages, C# has
sizeof as a static property but tellingly offers the equivalent of
sizeofValue (well, strideofValue) as a function in a different module.
Essentially every other C-family language that exposes pointers to the user
offers both of and ofValue equivalents. The question is, how does a user
with existing code using sizeofValue() migrate to Swift 3? I do not see a
viable answer with the MemoryLayout design.

···

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com> wrote:

I really like this idea. This IMO is lower level functionality than
`type(of:)` (née dynamicType), so I think it makes sense for it to be
grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so!
Is it the same as calling type(of:) then using that with MemoryLayout? I
imagine they could be fixit’d easily, and that they compile down to the
same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite
direction from dynamicType. There, something was changed from being
property-like to being function-like. Here, Dave's proposal would take
something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a
"magic" property visible on all types, which isn't something you can write
and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items
which makes their semantic relationship more clear. It also receives the
type via a generic argument rather than a function argument and makes the
properties static. That is more representative of what is actually
happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the
properties on MemoryLayout could also be made available as instance
properties and it could have an initializer that accepts an instance to T
and throws the value away. However, I'm not at all convinced this is
necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

2. Dave A. and others expressed the opinion that these should probably
not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and
alignofValue() are better off removed altogether. I don't know if people
are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Isn’t this a short-term concern? I thought that requirement was going away.

AFAIK there are still concerns about ambiguity - [Int] - is it an array with one element (Int.self), or is it [Int].self?

···

For this reason, this proposal prefers using no-label calls for types (otherwise they would have been ofType) and labeled calls for values:

print(sizeof(Int)) // works
print(sizeof(Int.self)) // works

func withoutLabel<T>(thetype: T.Type) -> Int { return sizeof(T) }
func withLabel<T>(label label: T.Type) -> Int { return sizeof(T) }

// Works
print(withoutLabel(Int))

// Works
print(withLabel(label: Int.self))

// Does not work
// error: cannot create a single-element tuple with an element label
// print(withLabel(label: Int))

So with this in mind:

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(X.self)`, when `X` is a class type, is the
/// same regardless of how many stored properties `X` has.
public func size<T>(_: T.Type) -> Int

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(of: a)`, when `a` is a class instance, is the
/// same regardless of how many stored properties `a` has.
public func size<T>(of: T) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(_: T.Type) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(of: T) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(_: T.Type) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(of: T) -> Int
-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

That proposal was returned for revision; as far as user ergonomics in Swift 3, .self is going to be a consideration. Best to find a solution
that reads nicely regardless of the situation with .self removal.

From the core team decision:

"The core team would definitely like to circle back to this proposal after Swift 3 is out the door."

I think we should consider the best long-term design.

Yes. While it is true that disturbing the language as little as
possible helps ensure acceptance, a proposal that makes incremental
steps when the best solution is already acheivable is at a great
disadvantage, as it creates needless churn for users.

···

on Thu Jun 02 2016, Matthew Johnson <swift-evolution@swift.org> wrote:

On Jun 2, 2016, at 10:03 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If that happens to be dropping labels great, but if not, maybe we
don’t want to do that just because it will look better in Swift 3 at
the cost of a better design when “.self” is not required.

Dave’s MemoryLayout approach avoids the question of labels entirely. This is another subtle nudge in that direction IMO.

On Thu, Jun 2, 2016 at 9:57 AM Matthew Johnson <matthew@anandabits.com> wrote:

On Jun 2, 2016, at 9:43 AM, Erica Sadun <erica@ericasadun.com> wrote:

Supporting Dave A, type-based calls are much more likely to be used than instance calls, unlike with dynamicType/type(of:)

Term stdlib search gist search Google site:github +swift
sizeof 157 169 4880
sizeofValue 4 34 584
alignof 44 11 334
alignofValue 5 5 154
strideof 347 19 347
strideofValue 4 5 163
Type-based calls like sizeof() are poor candidates for parameter labels. While it's acceptable to write sizeof(Int), but one
must write size(of: Int.self) (with the trailing self) when the function has a label.

Isn’t this a short-term concern? I thought that requirement was going away.

For this reason, this proposal prefers using no-label calls for types (otherwise they would have been ofType) and labeled
calls for values:

print(sizeof(Int)) // works
print(sizeof(Int.self)) // works

func withoutLabel<T>(thetype: T.Type) -> Int { return sizeof(T) }
func withLabel<T>(label label: T.Type) -> Int { return sizeof(T) }

// Works
print(withoutLabel(Int))

// Works
print(withLabel(label: Int.self))

// Does not work
// error: cannot create a single-element tuple with an element label
// print(withLabel(label: Int))

So with this in mind:

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(X.self)`, when `X` is a class type, is the
/// same regardless of how many stored properties `X` has.
public func size<T>(_: T.Type) -> Int

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(of: a)`, when `a` is a class instance, is the
/// same regardless of how many stored properties `a` has.
public func size<T>(of: T) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(_: T.Type) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(of: T) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(_: T.Type) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(of: T) -> Int
-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

Yes but, if they weren’t functions now, what would be the best design?

Dave's suggestions then were made in the context of a language that had
`.dynamicType`. The question today is how best to align these functions
with `type(of:)`. If we were to ignore this context, I'm not sure on what
basis we could judge whether a property or function is 'best' for these
facilities.

How many Swift developers will be using this functionality? Less than 1%?
I trust Dave’s judgement because he is in that small group.

I would caution against this assumption. I'm not a particularly advanced
developer by any stretch of the imagination, and I've been using
`strideof()` plenty of times while doing some math with
Accelerate.framework and Metal buffers. That said, Dave's in a very small
group indeed, the group that wrote these functions to start with.

···

On Thu, Jun 2, 2016 at 12:37 AM, Patrick Smith <pgwsmith@gmail.com> wrote:

On 2 Jun 2016, at 3:27 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com> wrote:

I really like this idea. This IMO is lower level functionality than
`type(of:)` (née dynamicType), so I think it makes sense for it to be
grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so!
Is it the same as calling type(of:) then using that with MemoryLayout? I
imagine they could be fixit’d easily, and that they compile down to the
same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite
direction from dynamicType. There, something was changed from being
property-like to being function-like. Here, Dave's proposal would take
something that's a function and turn it into a property. Hmm.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

2. Dave A. and others expressed the opinion that these should probably
not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and
alignofValue() are better off removed altogether. I don't know if people
are going to be happy about this idea.

Well, as I understand it, it's not actually possible to write your own type(of:), so we're going from a "magic" property to a "magic" function at least for now.

No, but you *can* write `func foo<T>(_ t: T)` which accepts any value (you *cannot* write a property that is available for all properties - that would require the ability to write `extension Any`. This is the distinction I am making. Of course the implementation is compiler magic no matter how we express it syntactically. But we can make it *appear* just like it might if the implementation *wasn’t* compiler magic. That makes it fit into the language better IMO and was the biggest motivator for changing `dynamicType`.

I'm most alarmed that one implication of the MemoryLayout proposal is loss of the `ofValue` family of functions. These functions don't fit with the design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`? But the response seems to be that these functions don't seem necessary at all and should be removed. "I don't see a use for it" is an insufficient justification for a feature removal. Looking to other languages, C# has sizeof as a static property but tellingly offers the equivalent of sizeofValue (well, strideofValue) as a function in a different module. Essentially every other C-family language that exposes pointers to the user offers both of and ofValue equivalents. The question is, how does a user with existing code using sizeofValue() migrate to Swift 3? I do not see a viable answer with the MemoryLayout design.

Going with MemoryLayout *does not* mean we would have to give up the value functions if we don’t want to:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

There's no good reason for this type to be generic. It should be non-generic and require the use of the instance properties.

It's actively harmful for this type to appear to be computed from a value. The layout is not in any way tied to the dynamic type of the value — for example, it is not the instance layout of the most-derived class or the value layout of the dynamic type of an existential. Furthermore, saying that it is computed from a value means that attempting to compute it from a type will succeed using the layout of the metatype, which seems like a catastrophic failure of API design.

John.

···

On Jun 2, 2016, at 8:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com <mailto:pgwsmith@gmail.com>> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a "magic" property visible on all types, which isn't something you can write and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items which makes their semantic relationship more clear. It also receives the type via a generic argument rather than a function argument and makes the properties static. That is more representative of what is actually happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the properties on MemoryLayout could also be made available as instance properties and it could have an initializer that accepts an instance to T and throws the value away. However, I'm not at all convinced this is necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Isn’t this a short-term concern? I thought that requirement was going away.

AFAIK there are still concerns about ambiguity - [Int] - is it an array with one element (Int.self), or is it [Int].self?

IIRC Joe Groff was going to work on sorting out the remaining issues but the plan is to move ahead eventually.

···

On Jun 2, 2016, at 10:01 AM, Charlie Monroe <charlie@charliemonroe.net> wrote:

For this reason, this proposal prefers using no-label calls for types (otherwise they would have been ofType) and labeled calls for values:

print(sizeof(Int)) // works
print(sizeof(Int.self)) // works

func withoutLabel<T>(thetype: T.Type) -> Int { return sizeof(T) }
func withLabel<T>(label label: T.Type) -> Int { return sizeof(T) }

// Works
print(withoutLabel(Int))

// Works
print(withLabel(label: Int.self))

// Does not work
// error: cannot create a single-element tuple with an element label
// print(withLabel(label: Int))

So with this in mind:

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(X.self)`, when `X` is a class type, is the
/// same regardless of how many stored properties `X` has.
public func size<T>(_: T.Type) -> Int

/// Returns the contiguous memory footprint of `T`.
///
/// Does not include any dynamically-allocated or "remote" storage.
/// In particular, `size(of: a)`, when `a` is a class instance, is the
/// same regardless of how many stored properties `a` has.
public func size<T>(of: T) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(_: T.Type) -> Int

/// Returns the least possible interval between distinct instances of
/// `T` in memory. The result is always positive.
public func spacing<T>(of: T) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(_: T.Type) -> Int

/// Returns the minimum memory alignment of `T`.
public func alignment<T>(of: T) -> Int
-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

And amended Alternatives with this. :)

- E

···

On Jun 2, 2016, at 9:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

https://github.com/erica/swift-evolution/blob/sizestride/proposals/XXXX-sidestride.md

-- E

···

On Jun 2, 2016, at 10:12 AM, Matthew Johnson <matthew@anandabits.com> wrote:

On Jun 2, 2016, at 11:04 AM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

On Jun 2, 2016, at 9:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }

And amended Alternatives with this. :)

Thanks! Can you change the init signature with Pyry’s improvement: `init(_: @autoclosure () -> T) {}`?

Well, as I understand it, it's not actually possible to write your own type(of:), so we're going from a "magic" property to a "magic" function at least for now.

No, but you *can* write `func foo<T>(_ t: T)` which accepts any value (you *cannot* write a property that is available for all properties - that would require the ability to write `extension Any`. This is the distinction I am making. Of course the implementation is compiler magic no matter how we express it syntactically. But we can make it *appear* just like it might if the implementation *wasn’t* compiler magic. That makes it fit into the language better IMO and was the biggest motivator for changing `dynamicType`.

I'm most alarmed that one implication of the MemoryLayout proposal is loss of the `ofValue` family of functions. These functions don't fit with the design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`? But the response seems to be that these functions don't seem necessary at all and should be removed. "I don't see a use for it" is an insufficient justification for a feature removal. Looking to other languages, C# has sizeof as a static property but tellingly offers the equivalent of sizeofValue (well, strideofValue) as a function in a different module. Essentially every other C-family language that exposes pointers to the user offers both of and ofValue equivalents. The question is, how does a user with existing code using sizeofValue() migrate to Swift 3? I do not see a viable answer with the MemoryLayout design.

Going with MemoryLayout *does not* mean we would have to give up the value functions if we don’t want to:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

···

On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com <mailto:pgwsmith@gmail.com>> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a "magic" property visible on all types, which isn't something you can write and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items which makes their semantic relationship more clear. It also receives the type via a generic argument rather than a function argument and makes the properties static. That is more representative of what is actually happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the properties on MemoryLayout could also be made available as instance properties and it could have an initializer that accepts an instance to T and throws the value away. However, I'm not at all convinced this is necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

And amended Alternatives with this. :)

Thanks! Can you change the init signature with Pyry’s improvement: `init(_: @autoclosure () -> T) {}`?

···

On Jun 2, 2016, at 11:04 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Jun 2, 2016, at 9:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

- E

Well, as I understand it, it's not actually possible to write your own type(of:), so we're going from a "magic" property to a "magic" function at least for now.

No, but you *can* write `func foo<T>(_ t: T)` which accepts any value (you *cannot* write a property that is available for all properties - that would require the ability to write `extension Any`. This is the distinction I am making. Of course the implementation is compiler magic no matter how we express it syntactically. But we can make it *appear* just like it might if the implementation *wasn’t* compiler magic. That makes it fit into the language better IMO and was the biggest motivator for changing `dynamicType`.

I'm most alarmed that one implication of the MemoryLayout proposal is loss of the `ofValue` family of functions. These functions don't fit with the design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`? But the response seems to be that these functions don't seem necessary at all and should be removed. "I don't see a use for it" is an insufficient justification for a feature removal. Looking to other languages, C# has sizeof as a static property but tellingly offers the equivalent of sizeofValue (well, strideofValue) as a function in a different module. Essentially every other C-family language that exposes pointers to the user offers both of and ofValue equivalents. The question is, how does a user with existing code using sizeofValue() migrate to Swift 3? I do not see a viable answer with the MemoryLayout design.

Going with MemoryLayout *does not* mean we would have to give up the value functions if we don’t want to:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

There's no good reason for this type to be generic. It should be non-generic and require the use of the instance properties.

Dave's initial suggestion was generic and Joe suggested static properties. I suppose it doesn't have to be generic if we pass the type directly to the initializer, but that design would eliminate the possibility of inferring the type from a value (which some people seem to want to retain).

I didn't mean to advocate either way about adding a value initializer and instance properties. I was only trying to show that it is *possible* to do that if we want to preserve the ofValue capabilities.

It's actively harmful for this type to appear to be computed from a value. The layout is not in any way tied to the dynamic type of the value — for example, it is not the instance layout of the most-derived class or the value layout of the dynamic type of an existential.

Understood, but that same problem exists for the current ofValue operations doesn't it? We can discuss removing them (I am not opposed to that), but that is independent of whether we should use a MemoryLayout struct as opposed to free functions.

I'm not trying to dictate the entire design. I'm saying that, if you're going to have a layout structure, I see no reason for it to be generic, and you should absolutely not make the primary way of constructing it be implicitly value-based.

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

Adding the label will eliminate the potential for confusion about type vs metatype. Wanting to know the size of the metatype is probably extremely rare, but there is not reason to prohibit it.

I agree that the label makes the problem better.

John.

···

On Jun 2, 2016, at 11:22 AM, Matthew Johnson <matthew@anandabits.com> wrote:
On Jun 2, 2016, at 12:01 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Jun 2, 2016, at 8:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

John.

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com <mailto:pgwsmith@gmail.com>> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a "magic" property visible on all types, which isn't something you can write and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items which makes their semantic relationship more clear. It also receives the type via a generic argument rather than a function argument and makes the properties static. That is more representative of what is actually happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the properties on MemoryLayout could also be made available as instance properties and it could have an initializer that accepts an instance to T and throws the value away. However, I'm not at all convinced this is necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Well, as I understand it, it's not actually possible to write your own type(of:), so we're going from a "magic" property to a "magic" function at least for now.

No, but you *can* write `func foo<T>(_ t: T)` which accepts any value (you *cannot* write a property that is available for all properties - that would require the ability to write `extension Any`. This is the distinction I am making. Of course the implementation is compiler magic no matter how we express it syntactically. But we can make it *appear* just like it might if the implementation *wasn’t* compiler magic. That makes it fit into the language better IMO and was the biggest motivator for changing `dynamicType`.

I'm most alarmed that one implication of the MemoryLayout proposal is loss of the `ofValue` family of functions. These functions don't fit with the design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`? But the response seems to be that these functions don't seem necessary at all and should be removed. "I don't see a use for it" is an insufficient justification for a feature removal. Looking to other languages, C# has sizeof as a static property but tellingly offers the equivalent of sizeofValue (well, strideofValue) as a function in a different module. Essentially every other C-family language that exposes pointers to the user offers both of and ofValue equivalents. The question is, how does a user with existing code using sizeofValue() migrate to Swift 3? I do not see a viable answer with the MemoryLayout design.

Going with MemoryLayout *does not* mean we would have to give up the value functions if we don’t want to:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

There's no good reason for this type to be generic. It should be non-generic and require the use of the instance properties.

Dave's initial suggestion was generic and Joe suggested static properties. I suppose it doesn't have to be generic if we pass the type directly to the initializer, but that design would eliminate the possibility of inferring the type from a value (which some people seem to want to retain).

I didn't mean to advocate either way about adding a value initializer and instance properties. I was only trying to show that it is *possible* to do that if we want to preserve the ofValue capabilities.

It's actively harmful for this type to appear to be computed from a value. The layout is not in any way tied to the dynamic type of the value — for example, it is not the instance layout of the most-derived class or the value layout of the dynamic type of an existential.

Understood, but that same problem exists for the current ofValue operations doesn't it? We can discuss removing them (I am not opposed to that), but that is independent of whether we should use a MemoryLayout struct as opposed to free functions.

Furthermore, saying that it is computed from a value means that attempting to compute it from a type will succeed using the layout of the metatype, which seems like a catastrophic failure of API design.

I was a bit hasty with the argument label and my example calling code wouldn't have actually worked. I should have included a clear external label.

This is what we would want to actually do (Erica, can you update again?):

init(ofValue: @autoclosure () -> T) { }

Used like this:

let sizeOfValue = MemoryLayout(ofValue: 42).size

Adding the label will eliminate the potential for confusion about type vs metatype. Wanting to know the size of the metatype is probably extremely rare, but there is not reason to prohibit it.

···

Sent from my iPad

On Jun 2, 2016, at 12:01 PM, John McCall <rjmccall@apple.com> wrote:

On Jun 2, 2016, at 8:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

John.

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a "magic" property visible on all types, which isn't something you can write and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items which makes their semantic relationship more clear. It also receives the type via a generic argument rather than a function argument and makes the properties static. That is more representative of what is actually happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the properties on MemoryLayout could also be made available as instance properties and it could have an initializer that accepts an instance to T and throws the value away. However, I'm not at all convinced this is necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree; in fact why aren’t these properties on the type itself? The type is what matters; why can’t the type just tell me it’s size?
Having free functions or magic operators seems to be another holdover from C.

    Int.size
    Int.alignment
    Int.spacing

    let x: Any = 5
    type(of: x).size

The compiler should be able to statically know the first three values and inline them. The second is discovering the size dynamically.

Russ

···

On Jun 2, 2016, at 11:30 AM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

John.

Two reasons. The first is that this is a user-extensible namespace via static members, so it's somewhat unfortunate to pollute it with names from the library. The second is that there's currently no language mechanism for adding a static member to every type, so this would have to be built-in. But I agree that in the abstract a static property would be preferable.

John.

···

On Jun 2, 2016, at 1:43 PM, Russ Bishop <xenadu@gmail.com> wrote:

On Jun 2, 2016, at 11:30 AM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

John.

I agree; in fact why aren’t these properties on the type itself? The type is what matters; why can’t the type just tell me it’s size?
Having free functions or magic operators seems to be another holdover from C.

    Int.size
    Int.alignment
    Int.spacing

    let x: Any = 5
    type(of: x).size

The compiler should be able to statically know the first three values and inline them. The second is discovering the size dynamically.

Well, as I understand it, it's not actually possible to write your own type(of:), so we're going from a "magic" property to a "magic" function at least for now.

No, but you *can* write `func foo<T>(_ t: T)` which accepts any value (you *cannot* write a property that is available for all properties - that would require the ability to write `extension Any`. This is the distinction I am making. Of course the implementation is compiler magic no matter how we express it syntactically. But we can make it *appear* just like it might if the implementation *wasn’t* compiler magic. That makes it fit into the language better IMO and was the biggest motivator for changing `dynamicType`.

I'm most alarmed that one implication of the MemoryLayout proposal is loss of the `ofValue` family of functions. These functions don't fit with the design: imagine, what is `MemoryLayout<Double>.size(ofValue: Float(42))`? But the response seems to be that these functions don't seem necessary at all and should be removed. "I don't see a use for it" is an insufficient justification for a feature removal. Looking to other languages, C# has sizeof as a static property but tellingly offers the equivalent of sizeofValue (well, strideofValue) as a function in a different module. Essentially every other C-family language that exposes pointers to the user offers both of and ofValue equivalents. The question is, how does a user with existing code using sizeofValue() migrate to Swift 3? I do not see a viable answer with the MemoryLayout design.

Going with MemoryLayout *does not* mean we would have to give up the value functions if we don’t want to:

struct MemoryLayout<T> {
    init() {}
    init(t: T) { /* throw away the value */ }
    
    // we could omit the static properties and require
    // writing MemoryLayout<Int>() if we don’t like the duplication
    static let size: Int
    static let spacing: Int
    static let alignment: Int

    let size: Int
    let spacing: Int
    let alignment: Int
}

let size = MemoryLayout<Int>.size
let sizeOfValue = MemoryLayout(42).size

There's no good reason for this type to be generic. It should be non-generic and require the use of the instance properties.

Dave's initial suggestion was generic and Joe suggested static properties. I suppose it doesn't have to be generic if we pass the type directly to the initializer, but that design would eliminate the possibility of inferring the type from a value (which some people seem to want to retain).

I didn't mean to advocate either way about adding a value initializer and instance properties. I was only trying to show that it is *possible* to do that if we want to preserve the ofValue capabilities.

It's actively harmful for this type to appear to be computed from a value. The layout is not in any way tied to the dynamic type of the value — for example, it is not the instance layout of the most-derived class or the value layout of the dynamic type of an existential.

Understood, but that same problem exists for the current ofValue operations doesn't it? We can discuss removing them (I am not opposed to that), but that is independent of whether we should use a MemoryLayout struct as opposed to free functions.

I'm not trying to dictate the entire design. I'm saying that, if you're going to have a layout structure, I see no reason for it to be generic, and you should absolutely not make the primary way of constructing it be implicitly value-based.

I'm interested to hear what others have to say about making this type generic or not. I don't have a strong opinion about that. I wonder if the initial motivation for that approach was that you would not create instances, just use the static properties.

I didn't consider the value-based initializer primary. The generic parameter and default initializer is what I considered primary (following the previous discussion).

We could have a primary initializer like this:

init(_ type: T.Type)

It would look better than a default initializer that requires the type to be passed as a generic argument. The fact that it is not labeled would make it clear that this is the primary initializer.

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

Sure. I don't necessarily disagree. But I think it's important to make clear that this is orthogonal to the struct vs free function discussion. That was the main point I was trying to make. :)

···

Sent from my iPad

On Jun 2, 2016, at 1:30 PM, John McCall <rjmccall@apple.com> wrote:

On Jun 2, 2016, at 11:22 AM, Matthew Johnson <matthew@anandabits.com> wrote:

On Jun 2, 2016, at 12:01 PM, John McCall <rjmccall@apple.com> wrote:

On Jun 2, 2016, at 8:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Adding the label will eliminate the potential for confusion about type vs metatype. Wanting to know the size of the metatype is probably extremely rare, but there is not reason to prohibit it.

I agree that the label makes the problem better.

John.

John.

On Thu, Jun 2, 2016 at 8:03 AM Matthew Johnson <matthew@anandabits.com> wrote:

Sent from my iPad

On Jun 2, 2016, at 12:27 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On Thu, Jun 2, 2016 at 12:24 AM, Patrick Smith <pgwsmith@gmail.com> wrote:
I really like this idea. This IMO is lower level functionality than `type(of:)` (née dynamicType), so I think it makes sense for it to be grouped under its own domain, the MemoryLayout type.

Plus MemoryLayout can be extended with new convenience methods.

I’m fine with those old methods being removed, but I never use them so! Is it the same as calling type(of:) then using that with MemoryLayout? I imagine they could be fixit’d easily, and that they compile down to the same underlying code.

I'm actually souring to the idea. It goes in the diametrically opposite direction from dynamicType. There, something was changed from being property-like to being function-like. Here, Dave's proposal would take something that's a function and turn it into a property. Hmm.

That's not a fair comparison though. With dynamicType we removed a "magic" property visible on all types, which isn't something you can write and turned it into a function (which is obviously something you can write).

Dave's MemoryLayout creates a new type to bundle together related items which makes their semantic relationship more clear. It also receives the type via a generic argument rather than a function argument and makes the properties static. That is more representative of what is actually happening and could help to prevent confusion.

If we really need an 'ofValue' option that infers T from a value the properties on MemoryLayout could also be made available as instance properties and it could have an initializer that accepts an instance to T and throws the value away. However, I'm not at all convinced this is necessary.

On 2 Jun 2016, at 3:05 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

2. Dave A. and others expressed the opinion that these should probably not be global functions; his preference was for:

MemoryLayout<T>.size // currently sizeof()
MemoryLayout<T>.spacing // currently strideof()
MemoryLayout<T>.alignment // currently alignof()

3. Dave A. proposed that sizeofValue(), strideofValue(), and alignofValue() are better off removed altogether. I don't know if people are going to be happy about this idea.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I do want to say that while I'm including this in Alternatives Considered (and will update as soon as we finish lunch), that I stand by the freestanding functions as preferable to this clever but extremely indirect approach.

I believe the MemoryLayout type introduces a level of indirection that is less helpful in the rare times the user will consume this functionality, that it clutters calls and adds cognitive burden for reading code.

Let me give you some examples:

let errnoSize = sizeof(errno.dynamicType)
return sizeof(UInt) * 8
sendBytes(from: &address, count: sizeof(UInt.self))
_class_getInstancePositiveExtentSize(bufferClass) == sizeof(_HeapObject.self)
bytesPerIndex: sizeof(IndexType))

In every example, calling a size function's clarity is simpler than using the Memory Layout approach:

let errnoSize = MemoryLayout.init(t: errno).size
return MemoryLayout<UInt>.size * 8
sendBytes(from: &address, count: MemoryLayout<UInt>.size)
_class_getInstancePositiveExtentSize(bufferClass) == MemoryLayout<_HeapObject.self>.size
bytesPerIndex: MemoryLayout<IndexType>.size

The full type specification lends the calls an importance and verbosity they don't deserve compared to their simpler counterparts. The eye is drawn every time to the "MemoryLayout<T>" pattern:

* Prominence of the type constructor
* Simplicity of the function call
* Number of code characters used
* Swift's adherence to a mantra of concision and clarity.

It fails all these. To put it in usability terms: it's a big stinking mess compared to the readability and eye tracking of the simpler function. (I've cc'ed in Chris Lattner, who has people who can test this kind of thing on call.)

-- E

···

On Jun 2, 2016, at 12:47 PM, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Jun 2, 2016, at 1:30 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Jun 2, 2016, at 11:22 AM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:
On Jun 2, 2016, at 12:01 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Jun 2, 2016, at 8:48 AM, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jun 2, 2016, at 10:38 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

We could have a primary initializer like this:

init(_ type: T.Type)

It would look better than a default initializer that requires the type to be passed as a generic argument. The fact that it is not labeled would make it clear that this is the primary initializer.

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

Sure. I don't necessarily disagree. But I think it's important to make clear that this is orthogonal to the struct vs free function discussion. That was the main point I was trying to make. :)

Adding the label will eliminate the potential for confusion about type vs metatype. Wanting to know the size of the metatype is probably extremely rare, but there is not reason to prohibit it.

I agree that the label makes the problem better.

John.

And mentioned.

https://github.com/erica/swift-evolution/blob/sizestride/proposals/XXXX-sidestride.md

-- E

···

On Jun 2, 2016, at 2:13 PM, Matthew Johnson <matthew@anandabits.com> wrote:
I don't disagree with the points you make. But one can argue that this is a good thing. It calls attention to code that requires extra attention and care. In some ways this is similar to 'UnsafeMutablePointer<T>' vs '*T'. Verbosity was a deliberate choice in that case.

If achievable, this would certainly be clean and elegant.

-- E

···

On Jun 2, 2016, at 2:43 PM, Russ Bishop <xenadu@gmail.com> wrote:

On Jun 2, 2016, at 11:30 AM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I still think the value-based APIs are misleading and that it would be better to ask people to just use a type explicitly.

John.

I agree; in fact why aren’t these properties on the type itself? The type is what matters; why can’t the type just tell me it’s size?
Having free functions or magic operators seems to be another holdover from C.

    Int.size
    Int.alignment
    Int.spacing

    let x: Any = 5
    type(of: x).size

The compiler should be able to statically know the first three values and inline them. The second is discovering the size dynamically.

Russ

I don't disagree with the points you make. But one can argue that this is a good thing. It calls attention to code that requires extra attention and care. In some ways this is similar to 'UnsafeMutablePointer<T>' vs '*T'. Verbosity was a deliberate choice in that case.

You know...rather than introducing a new type like MemoryLayout, would it make sense to do this with static properties on UnsafePointer?

  UnsafePointer<Int>.pointeeSize
  UnsafePointer<Int>.pointeeAlignment
  UnsafePointer<Int>.pointeeSpacing

If you need this information, 90% of the time you're probably using UnsafePointer or one of its friends, right?

···

--
Brent Royal-Gordon
Architechies