On Thu, 18 Oct 2018 at 13:41, Axel Wagner <axel.wagner...@googlemail.com> wrote:
> On Thu, Oct 18, 2018 at 2:06 PM roger peppe <rogpe...@gmail.com> wrote: > >> For generics, that analysis is trivial - there is no need to do any >> control flow analysis to determine the set of possible generic type >> parameters to a type or function (with the exception of recursive generic >> functions, which can be disallowed). >> >> For interfaces, the job is much harder. Guru can do it, but only to a >> limited extent. And in general it's not possible a) because the number of >> possible types is not bounded (you can create new types with the reflect >> package, or by dynamically loading modules) and b) because you'd need to >> solve the halting problem. >> > > I don't understand what you're trying to say. These two cases are not > relevant here, because you can't actually do them with the contracts design > - in fact, at least the reflection one is specifically called out in the > "Dual implementation" section of the overview. I never claimed the analysis > for interfaces is *easier*, I claimed that it's *exactly as hard.* > > Or, to put it another way: That "limited extend" you mention is exactly > the extend to which the compiler can do that proof for generics. So doing > it to that extend provides you with the same performance benefit. > > Or, if you prefer: The type-checker and/or heuristic for whether to > specialize a function for generics provides a blue-print for how to do the > equivalent analysis for interfaces. > It really doesn't, because interface values carry their types with them, whereas type parameters always stay as type parameters and cannot be directly stored in a value (unless you convert it to an interface value). You cannot take the dynamic type of an interface value and turn it into a type parameter unless you explicitly mention the type... at which point it's no longer dynamic. With type-parametric generics, you cannot return a value with a type that uses a generic type that's not passed in the type parameters. With interfaces, you can. With type-parametrics generics, you can expand all possible type parameters at compile time without needing to do any flow analysis. As an example: https://play.golang.org/p/68eHo313LZI. It's easy to find out all the possible types for the generic functions there. Here they are. repeat(string) repeat(int) repeat([]string) last([]string) index([]string) first(int) index(int) The algorithm to do it is quite straightforward: https://play.golang.org/p/subnLkSSxdI But in the case where your first paragraph applies - i.e. you can >>> statically know the full set of types a generic function or type is >>> instantiated with - the exact same analysis can also provide exactly the >>> same results for interface-based polymorphism. >>> >> >> It really can't. The analysis needed for parametric types need not look >> at anything other than type parameters. The analysis needed for interfaces >> needs to analyse the code itself. A few examples: >> https://play.golang.org/p/CEzBpsRIVGQ >> > > AFAICT none of these map to contracts either. > Actually they do - interface{} is equivalent to the contract(T){}. But I'm not sure what you're getting at there. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.