<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Yes, agreed, the fix for Chris’s brain-bender shouldn’t revisit any of SE-0155’s matching & labeling rules.</div><div class=""><br class=""></div><div class="">How about:</div><div class=""><br class=""></div><div class="">1. Disallow labels for bare tuples in patterns. (By “bare tuples” I mean “not representing associated values on an enum.”)</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let (a: x, b: y) = foo // disallowed</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let (x, y) = foo // OK</div></div><div class=""><br class=""></div><div class="">2. Maybe require “let” before individual identifiers when pattern matching on associated values, while preserving SE-0155’s rules for when labels may appear:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>case let .foo(a: x, b: y) // disallowed</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>case .foo(a: let x, b: let y) // OK</div></div><div class=""><br class=""></div><div class="">#2 is debatable. It would solve an enum-based parallel to Chris’s original:</div><div class=""><br class=""></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>case let .foo(a: Int, b: String) // disallowed</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>case .foo(a: let Int, b: let String) // allowed, and Int/String no longer look like types</div></div></div><div class=""><br class=""></div><div class="">P</div><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 16, 2017, at 10:55 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">See:</div><div class=""><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170417/035972.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170417/035972.html</a></div><div class=""><br class=""></div><div class=""><br class=""><div class="gmail_quote"><div class="">On Fri, Jun 16, 2017 at 22:32 Paul Cantrell <<a href="mailto:cantrell@pobox.com" class="">cantrell@pobox.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">Under these not-yet-implemented plans, if associated value labels are no longer tuple labels, then how will pattern matching work? And what existing pattern matching code will break / continue to work?</div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">P</div></div><div style="word-wrap:break-word" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 16, 2017, at 10:22 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="m_1611559154887191962Apple-interchange-newline"><div class=""><div class="">Keep in mind that once the latest proposal about enum cases is implemented, these will be at least notionally no longer tuple labels but rather a sugared way of spelling part of the case name. The rules surrounding labels during case matching have only just been revised and approved and have not even yet been implemented. I don’t think it would be wise to fiddle with them again.</div><div class=""><br class=""></div><div class=""><br class=""><div class="gmail_quote"><div class="">On Fri, Jun 16, 2017 at 21:21 Paul Cantrell <<a href="mailto:cantrell@pobox.com" target="_blank" class="">cantrell@pobox.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 16, 2017, at 5:23 PM, Mark Lacey <<a href="mailto:mark.lacey@apple.com" target="_blank" class="">mark.lacey@apple.com</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><div style="word-wrap:break-word" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 16, 2017, at 2:09 PM, Paul Cantrell <<a href="mailto:cantrell@pobox.com" target="_blank" class="">cantrell@pobox.com</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class=""><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline">On Jun 16, 2017, at 3:43 PM, Mark Lacey <<a href="mailto:mark.lacey@apple.com" target="_blank" class="">mark.lacey@apple.com</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><div style="word-wrap:break-word" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 16, 2017, at 1:21 PM, Mark Lacey <<a href="mailto:mark.lacey@apple.com" target="_blank" class="">mark.lacey@apple.com</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class=""><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline">On Jun 16, 2017, at 11:13 AM, Paul Cantrell via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><blockquote type="cite" class=""><div class=""><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline">On Jun 15, 2017, at 7:17 PM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:</div><br class="m_1611559154887191962m_8541429286439924002Apple-interchange-newline"><div class=""><div class=""><br class=""><div class="gmail_quote"><div class="">On Thu, Jun 15, 2017 at 19:03 Víctor Pimentel <<a href="mailto:vpimentel@tuenti.com" target="_blank" class="">vpimentel@tuenti.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class=""><div class="">On 16 Jun 2017, at 01:55, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><div class="gmail_quote"><div class="">On Thu, Jun 15, 2017 at 17:43 David Hart <<a href="mailto:david@hartbit.com" target="_blank" class="">david@hartbit.com</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">By the way, I’m not attempting to deduce that nobody uses this feature by the fact I didn’t know about it. But I think it’s one interesting datapoint when comparing it to SE-0110.</div></div></div></blockquote><div class=""><br class=""></div><div class=""><br class=""></div></div></div></div><div class=""><div class=""><div class="gmail_quote"><div class="">SE-0110, **in retrospect**, has had impacts on a lot of users; prospectively, it was thought to be a minor change, even after review and acceptance.</div><div class=""><br class=""></div><div class="">Keep in mind that this proposed change would also eliminate inline tuple shuffle. For instance, the following code will cease to compile:</div><div class=""><br class=""></div><div class=""><div class="">let x = (a: 1.0, r: 0.5, g: 0.5, b: 0.5)</div><div class="">func f(color: (r: Double, g: Double, b: Double, a: Double)) {</div><div class=""> print(color)</div><div class="">}</div></div><div class="">f(color: x)</div><div class=""><br class=""></div><div class="">It is an open question how frequently this is used. But like implicit tuple destructuring, it currently Just Works(TM) and users may not realize they’re making use of the feature until it’s gone.</div></div></div></div></blockquote><br class=""></div><div class=""><div class="">It's much much less used, by looking at open source projects I doubt that a significant portion of projects would have to change code because of this.</div></div></blockquote><div class=""><br class=""></div><div class="">The reason that I’m urging caution is because, if I recall correctly, that is also what we said about SE-0110 on this list. Then, as now, we were discussing an issue with something left over from the Swift 1 model of tuples. Then, as now, we believed that the feature in question was rarely used. Then, as now, we believed that removing that feature would improve consistency in the language, better both for the compiler and for users. Then, as now, leaving it in was thought to prevent moving forward with other features that could improve Swift.</div></div></div></div></blockquote><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Data:</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">I hacked up a regexp that will catch most uses of labeled tuples in pattern matches, e.g. “let (foo: bar) = baz”. That’s what we’re talking about, right?</div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">That’s the obvious example that people find confusing.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Less obvious places that labeled tuple patterns show up are ‘case let’ and ‘case’ (see below).<span class="m_1611559154887191962m_8541429286439924002Apple-converted-space"> </span></div></div></blockquote><div class=""><br class=""></div><div class="">Okay, I should have looked at your regex and read further. It looks like you were already trying to match these.</div></div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">I did walk the grammar for all occurrences of _pattern_.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">I’m only matching named tuple patterns that immediately follow one of the keywords which a pattern follows (for, case, let, var, and catch). As I mentioned, I’m not matching patterns that come later in comma-separated lists. I’m also not matching named tuples inside nested patterns, e.g. let ((a: b), (c: d)).</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">But again, if even the most basic form of this construct is so rare, I doubt more robust matching would turn up that much more usage.</div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div style="word-wrap:break-word" class=""><div class=""><div class="">I’m surprised you’re not seeing any uses of ‘case’ with labels.</div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Me too. But I just verified that my pattern does match them.</div></div></blockquote><div class=""><br class=""></div>Are you sure? It doesn’t look like it’s going to match the example I gave due to the leading ‘.’ on the enum case.</div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Ah! I should have read your original message more carefully. You’re quite right, I only was checking case statements for raw tuples like this:</div><div class=""><br class=""></div><div class=""> <span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(50,62,125)" class="">case</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(50,62,125)" class="">let</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures" class=""> (i: a, f: b):</span></div><div class=""><br class=""></div><div class="">…and not for anything involving associated values. I hadn’t even considered that associated values would be affected by this, but looking at the grammar it seems they would indeed be.</div><div class=""><br class=""></div><div class="">Another clumsy regex search, this time for patterns with tuple labels on associated values, turned up 111 results (one per ~3800 lines). Not super common, but certainly nothing to sneeze at. Here they are:</div><div class=""><br class=""></div><div class=""> <a href="https://gist.github.com/pcantrell/d32cdb5f7db6d6626e45e80011163efb" target="_blank" class="">https://gist.github.com/pcantrell/d32cdb5f7db6d6626e45e80011163efb</a></div><div class=""><br class=""></div><div class="">Looking through that gist, these usages mostly strike me as being just fine:</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .cover(from: .bottom):</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""><br class=""></span></font></div></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .reference(with: let ref):</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""><br class=""></span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .update(tableName: let tableName, columnNames: _):</span></font></div><div class=""><br class=""></div><div class="">I’d even say that removing the tuple labels would make things worse. Consider:</div><div class=""><br class=""></div><div class=""><div class=""><span style="font-size:11px;font-family:Menlo" class=""> case .name(last: let firstName, first: _): // mistake is clear</span></div><div class=""><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .name(</span></font><span style="font-family:Menlo;font-size:11px" class="">let</span><span style="font-family:Menlo;font-size:11px" class=""> </span><span style="font-size:11px;font-family:Menlo" class="">firstName, _): // mistake is buried</span></div></div><div class=""><br class=""></div></div><div class="">In Chris’s original brain-bending example, the confusion is that there’s no “let” after the colon, so Int and Float look like types instead of variable names:</div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> let (a : Int, b : Float) = foo()</span></font></div><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">However, in the examples in the gist above, most of the patterns either (1) declare variables using a `let` after the colon:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .reference(with: let ref):</span></font></div><div class=""><br class=""></div><div class="">…or (2) don’t declare a variable at all:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .string(format: .some(.uri)):</span></font></div><div class=""><br class=""></div><div class="">What if we allowed labels on associated values, but required a `let` after the colon to bind a variable?</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case let .a(b: c): // disallowed</span></font></div><div class=""><font face="Menlo" class=""><span style="font-size:11px" class=""> case .a(b: let c): // OK</span></font></div><div class=""><br class=""></div><div class="">Only 15 of those 111 run afoul of _that_ rule. Here they are:</div><div class=""><br class=""></div><div class=""> <a href="https://gist.github.com/pcantrell/9f61045d7d7c8d18eeec8ebbef6cd8f8" target="_blank" class="">https://gist.github.com/pcantrell/9f61045d7d7c8d18eeec8ebbef6cd8f8</a></div><div class=""><br class=""></div><div class="">That’s one breakage every ~28000 lines, which seems much more acceptable. The drawback is that you can’t declare variables for a bunch of associated value en masse anymore; you need one let per value. (See line 2 in that gist.)</div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div style="word-wrap:break-word" class=""><div class="">You might want to try the patch I sent as it will definitely catch any tuple pattern that makes it to the verifier and does have labels.</div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">I’m not set up to build the compiler, unfortunately. One of these days.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class="">P</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">Mark</div><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">P</div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><div class="">Mark</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Fortunately we do not appear to allow shuffling in these cases. I’m not sure if the human disambiguation is easier here because of the context (‘case let’ and ‘case’), but I don’t recall seeing complain about these being confusing (having said that it’s entirely possible they are very confusing the first time someone sees them, in particular ‘cast let’ and the binding form of ‘case’.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="">enum X {</div><div class=""> case e(i: Int, f: Float)</div><div class="">}</div><div class=""><br class=""></div><div class="">let x = X.e(i: 7, f: 12)</div><div class=""><br class=""></div><div class="">if case let X.e(i: hi, f: bye) = x {</div><div class=""> print("(i: \(hi), f: \(bye))")</div><div class="">}</div><div class=""><br class=""></div><div class="">func test(_ x: X, _ a: Int, _ b: Float) {</div><div class=""> switch x {</div><div class=""> case .e(i: a, f: b):</div><div class=""> print("match values")</div><div class=""> case .e(i: let _, f: let _):</div><div class=""> print("bind values")</div><div class=""> default:</div><div class=""> break</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">test(X.e(i: 1, f: 2), 1, 2)</div><div class="">test(X.e(i: 1, f: 2), 3, 4)</div><div class=""><br class=""></div></div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">I ran that against all 55 projects in swift-source-compat-suite, comprising about over 400,000 lines of Swift code, and found … drumroll … exactly one match:</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(226,226,226);background-color:rgba(2,3,50,0.952941)" class=""><span style="font-size:11px" class=""><span style="font-variant-ligatures:no-common-ligatures;color:rgb(55,191,41)" class=""><br class=""></span></span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(226,226,226);background-color:rgba(2,3,50,0.952941)" class=""><span style="font-size:11px" class=""><span style="font-variant-ligatures:no-common-ligatures;color:rgb(55,191,41)" class="">neota (swift-source-compat-suite)$<span class="m_1611559154887191962m_8541429286439924002Apple-converted-space"> </span></span><span style="font-variant-ligatures:no-common-ligatures" class="">find project_cache -name '*.swift' -print0 | xargs -0 pcregrep -M '(for|case|let|var|catch)\s+\([a-zA-Z0-9_]+\s*:'</span></span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(226,226,226);background-color:rgba(2,3,50,0.952941)" class=""><span style="font-variant-ligatures:no-common-ligatures;font-size:11px" class="">project_cache/RxSwift/RxExample/RxExample-iOSTests/TestScheduler+MarbleTests.swift: let (time: _, events: events) = segments.reduce((time: 0, events: [RecordedEvent]())) { state, event in</span></div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(226,226,226);background-color:rgba(2,3,50,0.952941)" class=""><span style="font-variant-ligatures:no-common-ligatures;font-size:11px" class=""><br class=""></span></div><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><br class=""></span></div><div class="">Caveats about this method:</div><div class=""><br class=""></div><div class="">• My regexp won’t match second and third patterns in a comma-separated let or case, e.g.:</div><div class=""><br class=""></div><div class=""> let a = b, (c: d) = e</div><div class=""><br class=""></div><div class="">• It doesn’t match non-ascii identifiers.</div><div class=""><br class=""></div><div class="">• This experiment only considers labeled tuples in pattern matches, what I took Chris’s original puzzler to be about. Label-based tuple shuffling is a separate question.</div><div class=""><br class=""></div><div class="">Still, even if it’s undercounting slightly, one breakage in half a million lines of code should put to rest concerns about unexpected widespread impact.</div><div class=""><br class=""></div><div class="">(Anything else I’m missing?)</div><div class=""><br class=""></div><div class="">• • •</div><div class=""><br class=""></div><div class="">Aside for those who know the tools out there: what would it take to run inspections like this against ASTs instead of using a regex? Could we instrument the compiler as Brent suggested?</div></div></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">If you want to catch *all* of these cases then the patch below will do it by failing the AST verifier when it hits a pattern with labels. If you only want to find the plain let-binding versions of this and not the ‘case let’ and ‘case’ ones, I’d suggest looking at the parser to see if there’s an easy place to instrument (I don’t know offhand).</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Mark</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="">diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp</div><div class="">index b59a7ade23..ba4b2a245d 100644</div><div class="">--- a/lib/AST/ASTVerifier.cpp</div><div class="">+++ b/lib/AST/ASTVerifier.cpp</div><div class="">@@ -2772,6 +2772,13 @@ public:</div><div class=""> }</div><div class=""> </div><div class=""> void verifyParsed(TuplePattern *TP) {</div><div class="">+ for (auto &elt : TP->getElements()) {</div><div class="">+ if (!elt.getLabel().empty()) {</div><div class="">+ Out << "Labeled tuple patterns are offensive!\n";</div><div class="">+ abort();</div><div class="">+ }</div><div class="">+ }</div><div class="">+</div><div class=""> PrettyStackTracePattern debugStack(Ctx, "verifying TuplePattern", TP);</div><div class=""> verifyParsedBase(TP);</div><div class=""> }</div><div class=""><br class=""></div></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class=""><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="">Or can SourceKit / SourceKitten give a full AST? Or has anybody written a Swift parser in Swift?</div><div class=""><br class=""></div><div class="">Cheers,</div><div class=""><br class=""></div><div class="">Paul</div><div class=""><br class=""></div></div><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="">_______________________________________________</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="">swift-evolution mailing list</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="mailto:swift-evolution@swift.org" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">swift-evolution@swift.org</a><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div></blockquote></div></div></blockquote></div></blockquote></div><br class=""></div></div></blockquote></div></div></blockquote></div></div>
</div></blockquote></div><br class=""></div></blockquote></div></div>
</div></blockquote></div><br class=""></body></html>