<div dir="ltr">This sounds similar to lenses. Have you looked at previous lens discussions on-list?<div><br></div><div>Nevin</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 23, 2017 at 3:28 AM, Daryle Walker via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I started a thread earlier this week about strong type-aliases and object aliases. Here’s a fuller proposal on object aliases.</div><div><br></div><div><h1 id="m_-6745906375947876979toc_0" style="margin:0px 0px 10px;padding:0px;font-size:28px;font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Feature name</h1><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><li style="margin:0px">Proposal: <a style="color:rgb(65,131,196);margin-top:0px">SE-NNNN</a></li><li style="margin:0px">Authors: <a href="https://github.com/CTMacUser" style="color:rgb(65,131,196);margin-top:0px" target="_blank">Daryle Walker</a>, <a href="https://github.com/swiftdev" style="color:rgb(65,131,196)" target="_blank">Author 2</a></li><li style="margin:0px">Review Manager: TBD</li><li style="margin:0px">Status: <strong style="margin-top:0px">Awaiting review</strong></li></ul><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><em>During the review process, add the following fields as needed:</em></p><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><li style="margin:0px">Decision Notes: <a href="https://lists.swift.org/pipermail/swift-evolution/" style="color:rgb(65,131,196);margin-top:0px" target="_blank">Rationale</a>, <a href="https://lists.swift.org/pipermail/swift-evolution/" style="color:rgb(65,131,196)" target="_blank">Additional Commentary</a></li><li style="margin:0px">Bugs: <a href="https://bugs.swift.org/browse/SR-NNNN" style="color:rgb(65,131,196);margin-top:0px" target="_blank">SR-NNNN</a>, <a href="https://bugs.swift.org/browse/SR-MMMM" style="color:rgb(65,131,196)" target="_blank">SR-MMMM</a></li><li style="margin:0px">Previous Revision: <a href="https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/NNNN-filename.md" style="color:rgb(65,131,196);margin-top:0px" target="_blank">1</a></li><li style="margin:0px">Previous Proposal: <a style="color:rgb(65,131,196);margin-top:0px">SE-XXXX</a></li></ul><h2 id="m_-6745906375947876979toc_1" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Introduction</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">This is a proposal to define aliases to objects.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Swift-evolution thread: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170619/037631.html" style="color:rgb(65,131,196)" target="_blank">1</a></p><h2 id="m_-6745906375947876979toc_2" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Motivation</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Aliasing allows a named object to actually refer to another object instead of newly-allocated storage. Referring to an object with a simple name isn't very useful, but referring to an object needing a complex expression to point to it can help with reducing typing.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">However, aliasing has a cost. Compilers have to make certain assumptions if objects can have multiple names referring to them, and these assumptions reduce what kinds of optimizations can be made.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Language design can make a difference in how code can be optimized. Languages like C and C++ assume aliasing is allowed by default, limiting how many optimizations can be done. More recent versions of C have a keyword ("<code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">restrict</code>") to ban certain objects from aliasing. Other languages go the other way; you need to take extra measures to alias objects, since object handling bars aliasing by default.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Swift is currently an alias-adverse language. The model for the equivalent of pointers is supposed to be for short-term use, and not persisted. Other constructs that would use references: read-write properties, read-write subscripts, and <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">inout</code> function parameters, can all be implemented by copy-in-then-copy-out, presumably to avoid alias dynamics and its anti-optimizations. So the scope of aliases here will be limited to local-scale renaming of object locations that the compiler can connect statically.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Yes, the use case is currently weak, but it is a stepping stone for stronger cases, like changing the interface of an object with (currently not in the language) strong type-aliases without copies.</p><h2 id="m_-6745906375947876979toc_3" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Proposed solution</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">The solution is to introduce a new kind of object declaration. It uses a new keyword <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">pose</code> in the same place as <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">let</code> or <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">var</code>. It must be initialized with an expression that specifies an object, and be typed with a layout-compatible type (like the <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">unsafeBitCast</code> function).</p><div style="font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><pre style="margin-top:15px;margin-bottom:15px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><code class="m_-6745906375947876979language-swift" style="margin:0px;padding:0px;border:none;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">struct Sample {
var test1 = (1, 2, 3, "apple")
//...
func trial1() {
pose firstTestNumber = test1.0
print(firstTestNumber) // prints "1"
//...
firstTestNumber = 4
print(test1.0) // prints "4"
}
}</code></pre></div><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">When an object is used, the compiler associates the object with some sort of location ID. An alias just reuses its original's ID instead of having one of its own.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Here, the substitution is simple, but longer chains are imaginable. With a local-scope limitation, aliases work kind-of like macro constants in C.</p><h2 id="m_-6745906375947876979toc_4" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Detailed design</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Add to the "Grammar of a Declaration":</p><blockquote style="margin:15px 0px;border-left-width:4px;border-left-style:solid;border-left-color:rgb(221,221,221);padding:0px 15px;color:rgb(119,119,119);font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><div style="margin:0px"><em>declaration</em> → <em>alias-<wbr>declaration</em></div></blockquote><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Add a new section "Grammar of an Alias Declaration":</p><blockquote style="margin:15px 0px;border-left-width:4px;border-left-style:solid;border-left-color:rgb(221,221,221);padding:0px 15px;color:rgb(119,119,119);font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><div style="margin:0px"><em>alias-declaration</em> → <em>attributes<wbr>_opt</em> <em>declaration-modifiers_opt</em><strong><wbr>pose</strong> <em>pattern-initializer-list</em></div></blockquote><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">An alias declaration can only be in the local scope of a function. Expressions that describe source objects must be:</p><ul style="margin:15px 0px;padding-left:30px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)"><li style="margin:0px">a named object, including function parameters</li><li style="margin:0px">a member of a qualifying tuple object</li><li style="margin:0px">a stored property of a qualifying <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">struct</code> (or <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">class</code>?) object</li></ul><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">A source object must have a lifetime at least as long as any aliases to it. A source object cannot have <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">willSet</code> and/or <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">didSet</code>obse<wbr>rvers. The alias poses as an object of its type annotation, defaulting to the source object's type if omitted. An annotation must be of the source object's type or a layout-compatible type. An alias has the same mutability status as its source object.</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">An alias has the same operations as its annotated type, using the storage of the source object. An alias used as an <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">inout</code> function argument is banned if it and at least one other <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">inout</code> argument share memory (in whole or in part).</p><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Since source objects are restricted to have their storage established statically, the compiler can reuse a source object's location ID when an alias to that source is referenced. Since an alias doesn't escape its containing function (any returns or <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">inout</code> action would copy to/from the source object), additional global aliasing checks are avoided.</p><h2 id="m_-6745906375947876979toc_5" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Source compatibility</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Besides the new keyword <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">pose</code>, which should be conditional if possible, the changes are additive. I don't think it is legal to currently use an identifier <code style="margin:0px 2px;padding:0px 5px;white-space:nowrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">pose</code> in its planned syntax, so there should be no code to migrate.</p><h2 id="m_-6745906375947876979toc_6" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Effect on ABI stability</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">The effects of aliases happen only during translation, reusing locations of either named objects or a sub-objects of named objects. Since they shouldn't escape the function containing them (and can't be sub-objects of another type), the ABI should be unaffected.</p><h2 id="m_-6745906375947876979toc_7" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Effect on API resilience</h2><p style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255)">Since aliases shouldn't leak out from being a function implementation aid, there should be no effect on the API.</p><h2 id="m_-6745906375947876979toc_8" style="margin:20px 0px 10px;padding:0px;font-size:24px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);font-family:Helvetica,arial,sans-serif;background-color:rgb(255,255,255)">Alternatives considered</h2><p style="margin-top:15px;margin-right:0px;margin-left:0px;font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:rgb(255,255,255);margin-bottom:0px!important">The alternative is to do nothing. This would currently make reuse of a sub-object for read-write a bit more wordy. But this facility may be more useful if making interface-wise different but layout-compatible types (like strong type-aliases) is added.</p></div><br><div>
<div style="color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><div>— </div><div>Daryle Walker<br>Mac, Internet, and Video Game Junkie<br>darylew AT mac DOT com </div></div>
</div>
<br></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>