> On Jun 23, 2016, at 1:48 PM, Sean Heber <[email protected]> wrote: > > So the only real downside of this is that if you don’t refer/use all of the > generic types in this sort of situation, then it couldn’t figure it out? So > the following wouldn’t be a problem even if rule 1 was eliminated because > this actually ties other.value to self’s value and implies that other must be > GenericBox<Contents>? > > struct GenericBox<Contents: AnyObject> { > let value: Contents > > func test(other: GenericBox) -> Bool { > return value === other.value > } > } > > I might be totally not understanding, though. :P
This would *not* work with my proposed change. Even though we could theoretically infer that the parameter must be a GenericBox<Contents> to make the === type check, in practice Swift’s type checker operates at the expression level. Global type inference is not something we’re considering, because of the compile-time cost, increased difficulty in producing localized diagnostics, and the loss of too much explicit type information. > > l8r > Sean > > >> On Jun 23, 2016, at 3:30 PM, Slava Pestov via swift-evolution >> <[email protected]> wrote: >> >> >>> On Jun 23, 2016, at 1:27 PM, Xiaodi Wu <[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]> wrote: >>> Simpler interpretation of a reference to a generic type with no arguments >>> >>> • Proposal: SE-9999 >>> • Author: Slava Pestov >>> • Status: Awaiting review >>> • Review manager: TBD >>> 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 >>> >>> 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)) >>> } >>> } >>> >>> 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. >>> >>> Detailed design >>> >>> This really just involves removing an existing piece of logic from the type >>> resolver code. >>> >>> Impact on existing code >>> >>> This will have a small impact on existing code that uses a pattern similar >>> to the above. >>> >>> Alternatives considered >>> >>> 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. >>> >>> 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] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
