> On Jun 23, 2016, at 1:39 PM, Xiaodi Wu <[email protected]> wrote: > > Good to know. I absolutely agree that the gains to be had here wouldn't be > worth a one-off hack.
If people are strongly (or even mildly) opposed to removing this rule, we can give some thought to a more general solution. I don’t feel very strongly about this proposal one way or another, it’s just a bit of ugly code in TypeCheckType.cpp that would be nice to remove, and a developer on Twitter recently noticed this behavior and found it surprising. > On Thu, Jun 23, 2016 at 15:36 Slava Pestov <[email protected] > <mailto:[email protected]>> wrote: >> On Jun 23, 2016, at 1:34 PM, Xiaodi Wu <[email protected] >> <mailto:[email protected]>> wrote: >> >> Sorry, it's I who is saying things all wrong. I meant to ask, is it feasible >> to keep both behaviors but have #2 "win" over #1, instead of getting rid of >> behavior #1 entirely? > > I suspect there might be some way, but I think it would have to be some kind > of one-off hack, which is not in line with our long-term goal of making the > type checker more maintainable and correct ‘by construction’. > >> >> On Thu, Jun 23, 2016 at 15:30 Slava Pestov <[email protected] >> <mailto:[email protected]>> wrote: >>> On Jun 23, 2016, at 1:27 PM, Xiaodi Wu <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> When you mention the difficulty of an alternative, is that to say that it's >>> not feasible for the GenericBox in the last example to be resolved as >>> GenericBox<T>? From an end-user point of view, that seems to be the most >>> sensible behavior. >> >> With my proposed change, GenericBox would be resolved as GenericBox<T> in >> the last example. Right now it fails to type check. >> >> Here is an example that works right now, but would not work with my proposed >> change: >> >> struct GenericBox<Contents> { >> // Currently Swift resolves this as ‘GenericBox<Contents>’ >> // With the new rule, we cannot infer the parameter, because there’s no >> expression to infer it from >> func combine(other: GenericBox) { >> … >> } >> } >> >> Basically the meaning of ‘GenericBox’ right now depends on whether it >> appears inside its own definition or extension thereof, or not. The behavior >> when it appears elsewhere is more general — we infer the parameters from the >> surrounding expression, instead of assuming they’re equal to the context >> parameters. >> >> This is a subtle change — definitely let me know if I’m not explaining it >> well. >> >> Slava >> >>> On Thu, Jun 23, 2016 at 15:14 Slava Pestov via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> Simpler interpretation of a reference to a generic type with no arguments >>> >>> Proposal: SE-9999 >>> <https://github.com/slavapestov/swift-evolution/blob/silly-proposals/proposals/9999-simplify-unbound-generic-type.md> >>> Author: Slava Pestov <https://github.com/slavapestov> >>> Status: Awaiting review >>> Review manager: TBD >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#introduction>Introduction >>> >>> This proposal cleans up the semantics of a reference to a generic type when >>> no generic arguments are applied. >>> >>> Swift-evolution thread: Discussion thread topic for that proposal >>> <http://news.gmane.org/gmane.comp.lang.swift.evolution> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#motivation>Motivation >>> >>> Right now, we allow a generic type to be referenced with no generic >>> arguments applied in a handful of special cases. The two primary rules here >>> are the following: >>> >>> If the scope from which the reference is made is nested inside the >>> definition of the type or an extension thereof, omitting generic arguments >>> just means to implicitly apply the arguments from context. >>> >>> For example, >>> >>> struct GenericBox<Contents> { >>> let contents: Contents >>> >>> // Equivalent to: func clone() -> GenericBox<Contents> >>> func clone() -> GenericBox { >>> return GenericBox(contents: contents) >>> } >>> } >>> >>> extension GenericBox { >>> func print() { >>> // Equivalent to: let cloned: GenericBox<Contents> >>> let cloned: GenericBox = clone() >>> print(cloned.contents) >>> } >>> } >>> If the type is referenced from an unrelated scope, we attempt to infer the >>> generic parameters. >>> >>> For example, >>> >>> func makeABox() -> GenericBox<Int> { >>> // Equivalent to: GenericBox<Int>(contents: 123) >>> return GenericBox(contents: 123) >>> } >>> The problem appears when the user expects the second behavior, but instead >>> encounters the first. For example, the following does not type check: >>> >>> extension GenericBox { >>> >>> func transform<T>(f: Contents -> T) -> GenericBox<T> { >>> // We resolve 'GenericBox' as 'GenericBox<Contents>', rather than >>> // inferring the type parameter >>> return GenericBox(contents: f(contents)) >>> } >>> } >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#proposed-solution>Proposed >>> solution >>> >>> The proposed solution is to remove the first rule altogether. If the >>> generic parameters cannot be inferred from context, they must be specified >>> explicitly with the usual Type<Args...> syntax. >>> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#detailed-design>Detailed >>> design >>> >>> This really just involves removing an existing piece of logic from the type >>> resolver code. >>> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#impact-on-existing-code>Impact >>> on existing code >>> >>> This will have a small impact on existing code that uses a pattern similar >>> to the above. >>> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#alternatives-considered>Alternatives >>> considered >>> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#status-quo>Status >>> quo >>> >>> We could keep the current behavior, but one can argue it is not very >>> useful, and adds a special case where one is not needed. >>> >>> >>> <https://github.com/slavapestov/swift-evolution/tree/silly-proposals/proposals#more-complex-inference-of-generic-parameters>More >>> complex inference of generic parameters >>> >>> We could attempt to unify the two rules for resolving a reference to a >>> generic type with no arguments, however this presents theoretical >>> difficulties with our constraint solver design. Even if it were easy to >>> implement, it would increase type checking type by creating new >>> possibilities to consider, with very little actual benefit. >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
