<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Apr 22, 2016, at 6:08 PM, John McCall &lt;<a href="mailto:rjmccall@apple.com" class="">rjmccall@apple.com</a>&gt; wrote:</div><br class="Apple-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; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Apr 22, 2016, at 3:33 PM, Douglas Gregor via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi all,<div class=""><br class=""></div><div class="">A common complaint with protocol conformance checking is that it’s easy to make a little mistake when trying to implement a protocol requirement that has a default implementation. Here is a silly example:</div><div class="">[snip]</div><div class=""><br class=""></div><div class="">Naturally, this handles typos as well, e.g.,</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">t2.swift:12:8:<span class="Apple-converted-space">&nbsp;</span></span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(213, 59, 211);">warning:<span class="Apple-converted-space">&nbsp;</span></span><span class="" style="font-variant-ligatures: no-common-ligatures;">instance method 'foob(value:)' nearly matches optional requirement 'foo(value:)' of protocol 'P'</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; func foob(value: Float) { }</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(52, 189, 38); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; ^</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(255, 255, 255); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">t2.swift:12:8:<span class="Apple-converted-space">&nbsp;</span></span><span class="">note:<span class="Apple-converted-space">&nbsp;</span></span><span class="" style="font-variant-ligatures: no-common-ligatures;">rename to 'foo(value:)' to satisfy this requirement</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; func foob(value: Float) { }</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(52, 189, 38); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; ^~~~</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; foo</span></div></div><div class=""><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="">Running this on the standard library produces a number of results:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">/Users/dgregor/Projects/swift/swift/stdlib/public/core/Arrays.swift.gyb:726:24: warning: instance method 'removeLast()' nearly matches optional requirement 'removeFirst()' of protocol 'RangeReplaceableCollection'</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; public mutating func removeLast() -&gt; Element {</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">/Users/dgregor/Projects/swift/swift/stdlib/public/core/Arrays.swift.gyb:726:24: note: rename to 'removeFirst()' to satisfy this requirement</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; public mutating func removeLast() -&gt; Element {</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^~~~~~~~~~</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; removeFirst</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">/Users/dgregor/Projects/swift/swift/stdlib/public/core/Arrays.swift.gyb:726:24: note: move 'removeLast()' to another extension to silence this warning</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; public mutating func removeLast() -&gt; Element {</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">/Users/dgregor/Projects/swift/swift/stdlib/public/core/RangeReplaceableCollection.swift:158:17: note: requirement 'removeFirst()' declared here</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; mutating func removeFirst() -&gt; Iterator.Element</span></div><div class="" style="margin: 0px; font-size: 10px; line-height: normal; font-family: Monaco; color: rgb(196, 196, 196); background-color: rgb(0, 0, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ^</span></div></div></div></div></blockquote><div class=""><br class=""></div>Would a word-by-word edit-distance heuristic work better? &nbsp;That is, removeFirst is not a plausible typo for removeLast because First is not a plausible typo for Last.</div></div></blockquote><br class=""></div><div>A word-by-word edit distance seems to imply that if *any* word is too far off, reject. I’m a bit concerned that it would create false negatives.</div><div><br class=""></div><div>One possibility in this space would be to remove common words from consideration. That way, only the mismatching words will be used to do the edit-distance computation, so the one-mistake-per-N-characters-typed heuristic wouldn’t consider the completely-matching parts.</div><div><br class=""></div><div>In defense of the warning in this case: RangeReplaceableCollection has a “removeFirst” but not a “removeLast”; the conforming type here is implementing “removeLast” but not “removeFirst”. It is *so easy* to imagine this as programmer error that the warning feels justified.</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div><br class=""></div><br class=""></body></html>