<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 Jul 6, 2016, at 10:43 AM, 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=""><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=""><br class="Apple-interchange-newline">On Jul 1, 2016, at 15:53, Russ Bishop &lt;<a href="mailto:xenadu@gmail.com" class="">xenadu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 30, 2016, at 4:23 PM, Jordan Rose via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">[Proposal:&nbsp;<a href="https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md</a>&nbsp;]</div><div class=""><br class=""></div><div class="">I’m pretty concerned about completely removing this feature. Yes, it’s a type-checker / decl-checker nightmare, but I think Paolo’s example in the initial discussion showed how it’s being used effectively today. I’d much rather have some kind of inference marker that maps one-to-one between an associated type and a value requirement (method, initializer, property, or subscript), also as brought up in the original discussion.&nbsp;</div><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class="">protocol OptionA {</div><div class="">&nbsp; associatedtype Index</div><div class=""><br class=""></div><div class="">&nbsp; @infers(Index)</div><div class="">&nbsp; var startIndex: Index { get }</div><div class=""><br class=""></div><div class="">&nbsp; var endIndex: Index { get }</div><div class="">}</div><div class=""><br class=""></div><div class=""><div class="">protocol OptionB {</div><div class="">&nbsp; @inferredFrom(startIndex) // allows a full name here for overload resolution</div><div class="">&nbsp; associatedtype Index</div><div class=""><br class=""></div><div class="">&nbsp; var startIndex: Index { get }</div><div class="">&nbsp; var endIndex: Index { get }</div><div class="">}&nbsp;</div><div class=""><br class="Apple-interchange-newline">protocol OptionC {</div><div class="">&nbsp; associatedtype Index in startIndex // sugar</div><div class=""><br class=""></div><div class="">&nbsp; var startIndex: Index { get }</div><div class="">&nbsp; var endIndex: Index { get }</div><div class="">}</div></div></blockquote><br class=""><div class="">OptionC is the prettiest, but OptionA is probably the most flexible (consider overloading on associated types).</div><div class=""><br class=""></div><div class="">I know we want to lock down on things now, and I know we can do better in the future, but I think inferring associated types is really quite common, and I’m concerned about taking it out without giving people a good alternative. This<span class="Apple-converted-space">&nbsp;</span><i class="">is</i>&nbsp;just an impression, though.</div><div class=""><br class=""></div><div class="">Jordan</div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""><div class=""><div class="">I’m trying to fill a gap in my own knowledge here. How does explicitly stating that startIndex is the inference point for Index help?&nbsp;</div><div class=""><br class=""></div><div class="">Is it because various extensions and default implementations can provide different concrete types for Index, so the type checker is trying to resolve the ambiguity? If that’s the case, specifying startIndex here restricts the defaults/extensions that need to be considered from all to just ones that implement startIndex? Is that good enough generally or does it just solve the standard library’s problems?</div><div class=""><br class=""></div><div class="">Would it be enough to have rules along these lines for a concrete type adopting a protocol with associated types?</div></div><div class=""><br class=""></div><div class="">1. If the type’s main declaration (not defaults or extensions) contains a member satisfying a protocol requirement (where the requirement is specified in terms of an associated type) the associated type is locked to the type used in that member, so no global inference is necessary. If more than one such member is present all must use the same exact type.</div><div class="">2. Otherwise if there exists only one default/extension satisfying the associated type, the type used in that default implementation is used.</div><div class="">3. In all other cases the user must specify the associated types explicitly.</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; 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="">I don't remember exactly how the current rules work, but I think the compiler looks at<span class="Apple-converted-space">&nbsp;</span><i class="">all</i>&nbsp;the members that mention an associated type and tries to figure out if they're all in sync. Reducing that to just looking at<span class="Apple-converted-space">&nbsp;</span><i class="">one</i>&nbsp;value requirement might be enough to satisfy Doug's concerns, even if it still has to do overload resolution…or you could follow the spirit of your rule 2 and say that<span class="Apple-converted-space">&nbsp;</span><i class="">any</i>&nbsp;overloads force you to specify the element type explicitly.</div></div></blockquote><div><br class=""></div><div>The compiler currently looks at all of the requirements that mention any of the associated types, then matches each requirement up to all potential declarations that might satisfy the requirement (whether they come from the concrete type, its extensions, or some protocol extension doesn’t matter) to infer potential types for each associated type requirement. A potential solution to the problem assigns a type for each associated type requirement, which then needs to be checked as a whole (e.g., did the type we infer for SubSequence meet the Sequence requirement, and is its Element type the same as our Element type?). When there are multiple possible solutions, they’re ranked based on which declarations were used to satisfy a particular requirement—a declaration from the concrete type is usually better than one from a protocol extension, for example—so one solution can be chosen.</div><div><br class=""></div><div>And, really, you should be doing this for all protocol conformances at once, because they often share associated type names. That’s not implemented.</div><div><br class=""></div><div>So, back to the restriction: it certainly does help to only be considering one *requirement* for each inferrable associated type, but you’re still considering each possible declaration that can satisfy that requirement. It reduces the state space, but you’re still looking at complete solutions across several associated types and potential declarations that satisfy each requirement we inferred from.</div><div><br class=""></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; 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="">Rule 1, however, is the important one: "if more than one such member is present all must use the same exact type". I think that's already moving into the realm of spooky action and circularity issues that Doug's attempting to squash.</div></div></blockquote><br class=""></div><div>We already implement Rule 1.</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>