<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">I see. Would “@fixedSize” or “@abi(size)” be better names? In other words, the developer promises that whatever size the struct is now, it will be that way forever?</div><div class=""><br class=""></div><div class="">Also, wouldn’t the Pair&lt;A&gt; example below require that ‘A’ also be @fixedContents? Otherwise what does @fixedContents mean if the elements aren’t fixed?</div><div class=""><br class=""></div><div class="">Dave</div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Sep 6, 2017, at 13:44, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I don't think that's the right way to think about it either. It's purely an optimization tool to say "I won't add anything else to this struct", which means the compiler can avoid indirection when manipulating the struct across module boundaries. We could implement it with dynamic offset symbols and still see some benefit, but in this case we really ought to be able to get all the way to C-level performance.<div class=""><br class=""></div><div class="">The name hasn't been formalized; this will all go through swift-evolution at some point. We thought about "fixed-layout" in the past, but that doesn't have the right connotations for something like Pair:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">@fixedContents</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">public struct Pair&lt;A&gt; {</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; public var first: A</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; public var second: A</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">&nbsp; public init(first: A, second: A) { … }</blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class="">}</blockquote><div class=""><br class=""></div><div class="">This has known properties, but the layout depends on the generic argument, and if the generic argument is itself a type with unknown size then the actual layout won't be known until runtime.</div><div class=""><br class=""></div><div class="">Jordan</div><div class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Sep 6, 2017, at 10:40, David Zarzycki &lt;<a href="mailto:zarzycki@icloud.com" class="">zarzycki@icloud.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Ah, now that I see the CGPoint example, I understand. Thanks! Ya, the “hard” user-experience model I brought up feels wrong for CGPoint, etc. (For non-Apple people, CGPoint is a struct of two doubles on 64-bit machines add two floats on 32-bit machines.)<div class=""><div class=""><br class=""></div><div class="">It wasn’t obvious to me from context that @fixedContents wasn’t / isn’t for people trying to design a comprehensive ABI (disk, wire, etc), but just the machine specific in memory ABI. I wish the name was better, but nothing better seems obvious. (“@inMemoryABI”?)</div><div class=""><div class=""><br class=""></div><div class="">Dave<br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Sep 6, 2017, at 13:11, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">I'd be okay with <i class="">allowing</i>&nbsp;the ABI attributes to control ordering, but I would definitely not <i class="">require</i>&nbsp;them on every fixed-contents struct. We hope making a struct fixed-contents isn't something people have to do too often, but we don't want to drop them all the way into "hard" land when they do it. That is, "CGPoint" can't already be "hard mode".</div><div class=""><br class=""></div><div class="">Jordan</div><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Sep 6, 2017, at 05:13, David Zarzycki &lt;<a href="mailto:zarzycki@icloud.com" class="">zarzycki@icloud.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Jordan,<div class=""><br class=""></div><div class="">I really doubt that “belt and suspenders” ABI attributes would drive people to C, but reasonable people can certainly disagree on that.</div><div class=""><br class=""></div><div class="">Bertrand, when he was at Apple, used to say that “easy things should be easy, and hard things should be possible”.</div><div class=""><br class=""></div><div class="">I think ABI related attributes fall into the latter category. In particular, I think that trying to make ABI attributes too convenient only does programmers a disservice in the long run because most programmers aren't experts, and the cost of ignorance is huge when trying to do ABI design.</div><div class=""><br class=""></div><div class="">With these thoughts in mind, I think that is reasonable for the language to say: “If you want explicit control over a dimension of ABI decisions, then you must deal with all of the associated complexity. Here is a pointer to the documentation on dimension X that you were/are trying to explicitly manage. If that is ’too hard’ for you, then you probably shouldn’t be locking down this dimension of complexity yet.”</div><div class=""><br class=""></div><div class="">Dave<br class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Sep 5, 2017, at 20:11, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Hm. This is definitely an option, but I don't think it's really an acceptable user experience. This feels like it'll drive people all the way to declaring their types in C because Swift makes it too hard.</div><div class=""><br class=""></div><div class="">We do expect to have a tool to diff old and new modules at some point, but we could do something even simpler here: make a public symbol with the struct's layout in its name. That way, even 'nm' can tell if the symbol disappears. (Of course, public symbols do have a small cost, since this might not actually be the best idea.)</div><div class=""><br class=""></div><div class="">Another idea would be to restrict @fixedContents to require that all stored properties appear contiguously in the struct, possibly even pinned to the top or bottom, to indicate that order's not completely arbitrary. Again, that's just an improvement, not full protection.</div><div class=""><br class=""></div><div class="">Jordan</div><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Sep 5, 2017, at 13:00, David Zarzycki &lt;<a href="mailto:zarzycki@icloud.com" class="">zarzycki@icloud.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Jordan,<div class=""><br class=""></div><div class="">Thanks for thinking about this. For whatever it may be worth, I’m concerned about 1) the ability to reorder declarations and 2) the “either/or” nature of this proposal.</div><div class=""><br class=""></div><div class="">First, reordering: The ability to reorder declarations is deeply ingrained into the subconsciousness of Swift programmers and for good reasons. I think adding localized declaration order sensitivity is likely to be very brittle and regrettable in the long run. I also think this problem is made worse by having a type declaration context attribute because it can easily get lost in the noise of nontrivial declarations. The net result is that people will frequently forget about local order sensitivity. Yes, the compiler can engage in heroics and compare the previous module ABI and the new module ABI for conflicts, but that seems risky, complex, slow, and differently error prone.</div><div class=""><br class=""></div><div class="">Second, the “either/or” nature of this proposal: What do you think about a lightweight “belt and suspenders” solution whereby @fixedContents requires that stored properties be lightly annotated with their layout order? For example:</div><div class=""><div class=""><br class=""></div><div class=""><font face="Courier" class="">@fixedContents(3) struct Foo {</font></div><div class=""><font face="Courier" class="">&nbsp; @abi(0) var x: Int</font></div><div class=""><font face="Courier" class="">&nbsp; func a() {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; // a thousand lines of ABI layout distraction</font></div><div class=""><font face="Courier" class="">&nbsp; }</font></div><div class=""><font face="Courier" class="">&nbsp; @abi(1) var y: Double</font></div><div class=""><div class=""><font face="Courier" class="">&nbsp; func b() {</font></div><div class=""><font face="Courier" class="">&nbsp; &nbsp; // another thousand lines of ABI layout distraction</font></div><div class=""><font face="Courier" class="">&nbsp; }</font></div></div><div class=""><font face="Courier" class="">&nbsp; @abi(2) var z: String</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><br class=""></div><div class="">That would enable both renaming and reordering, would it not? This approach would also aid the compiler in quickly&nbsp;detecting hastily added/deleted declarations too because the count of @abi([0-9]+) declarations wouldn’t match the number passed to @fixedContents.</div><div class=""><br class=""></div><div class="">Dave</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Sep 5, 2017, at 14:59, Jordan Rose via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hey, all. In preparation for the several proposals we have to come this year, I&nbsp;<a href="https://github.com/apple/swift/pull/11742" class="">cleaned up docs/LibraryEvolution.rst</a>&nbsp;a little bit based on what's changed in Swift 4. This is mostly just mentioning things about generic subscripts, but there is one issue that I remember John bringing up some time in this past year: once you've made a struct fixed-contents, what can you change about its stored properties?<div class=""><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">To opt out of this flexibility, a struct may be marked '@fixedContents'. This promises that no stored properties will be added to or&nbsp;removed from the struct, even non-public ones.<br class=""></blockquote><div class=""><br class=""></div>Interestingly, this means that you <i class="">can</i>&nbsp;have non-public members of a fixed-contents struct. This is actually pretty sensible: it's the equivalent of a C++ class with non-public fields but a defaulted, inlinable copy constructor. Any inlinable members can access these properties directly as well; it's just outsiders that can't see them. But if inlinable code can reference these things, and if we really want them to be fast, that means they have to have a known offset at compile-time.</div><div class=""><br class=""></div><div class="">Now, we don't plan to stick to C's layout for structs, even fixed-contents structs. We'd really like users to not worry about manually packing things into trailing alignment space. But we still need a way to lay out fields consistently; if you have two stored properties with the same type, <i class="">one</i>&nbsp;of them has to go first. There are two ways to do this: sort by name, and sort by declaration order. <b class="">That means we can <i class="">either</i>&nbsp;allow reordering <i class="">or</i>&nbsp;allow renaming, but not both</b>. Which do people think is more important?</div><div class=""><br class=""></div><div class="">At the moment I'm inclined to go with "allow renaming" just because that's what C does. It's not great because you're allowed to reorder nearly everything else in the language, but there's a "least surprise" principle here that I think is still useful. It'd be surprising for the name of a non-public property to affect your library's&nbsp;<i class="">ABI</i>.</div><div class=""><br class=""></div><div class=""><div class="">(In theory we could also make different decisions for public and non-public fields, because it's much less likely to want to change the name of a public property. But you could do it without breaking source compatibility by introducing a computed property at the same time as you do the renaming. It's up to us whether that should break binary compatibility or not.)</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Note that because the layout algorithm isn't public, Swift isn't going to allow the thing from C where you have an existing field and you split it into two smaller fields. You can use computed properties for that instead. (Strictly speaking this probably isn't even good C because the fields in your struct can affect by-value calling conventions.)</div><div class=""><br class=""><div class=""><br class=""></div><div class="">By the way, I'm putting this on swift-dev because we're nowhere near a proposal and I want to keep the discussion narrow for now, but of course this point will be called out when the fixed-contents attribute—whatever its final form—goes to swift-evolution for a proper review.</div><div class=""><br class=""></div><div class="">Thanks!</div><div class="">Jordan</div></div></div></div>_______________________________________________<br class="">swift-dev mailing list<br class=""><a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-dev" class="">https://lists.swift.org/mailman/listinfo/swift-dev</a><br class=""></div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></div></div></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div></body></html>