Live data from Hacker News

How generics are implemented in Go 1.18

github.com

51–60 of 228 posts

Re: How generics are implemented in Go 1.18

#51
post #29

Earlier quoted context omitted.

Go does not have subtypes, so your question is not applicable.

It does have subtyping relationships via interface. It absolutely has subtypes in the co/contravariance. In theory, a slice of structs that implement an interface should be able to be used as a slice of that interface. But due to the implementation, that requires a full copy.

It’s not just a random implementation artifact. Since all slices in Go are mutable, it logically wouldn’t make sense to upcast them while keeping the reference. That would mean the ability to put other objects in the slice. Same for pointers.

That’s a basic fact of type safety that people often get wrong. For example, the JVM famously allows upcasting arrays, with very surprising results.

Re: How generics are implemented in Go 1.18

#52
post #42

Earlier quoted context omitted.

Rust also has (relatively) bad compile times due to generics. Not as bad as C++, but you can notice it's significantly worse than Go.

Rust does compile slower than Go, but it's not due to generics. It's mostly due to LLVM codegen and procedural macros. Go has the benefit of not relying on LLVM and not having procedural macros.

Absolutely true. I’d add that Rust is also doing a lot more expensive optimizations in release builds.

Re: How generics are implemented in Go 1.18

#53
post #29

Earlier quoted context omitted.

Go does not have subtypes, so your question is not applicable.

It does have subtyping relationships via interface. It absolutely has subtypes in the co/contravariance. In theory, a slice of structs that implement an interface should be able to be used as a slice of that interface. But due to the implementation, that requires a full copy.

No it's not due to the implementation, it's due to the language specification: there is no general subtyping.

You can see it this way: there is implicit syntactic sugar that creates an interface value (pointer + type info) when you assign a value of type T to a variable of type interface I where T implements I. This happens on variable assignment, function parameter bindings and return value bindings.

A slice of Is is just a very different type from a slice of Ts. The assignment magic sugar works, but it works at the level of slice elements, not the whole slice.

Re: How generics are implemented in Go 1.18

#54

Disclaimer: I only very occasionally touch Go code. Hasn't this been a very long time coming? Iirc there has been much dispute over this in the community. Can anyone weigh in on what the other options were?

I only occasional do language design / compiler writing projects, or work with compiler internals. Most people are really bad at estimating the implementation complexity and tradeoffs inherent in various language features. I'd say that C++ serves as a warning to others... think before you add features to your language, or you'll end up a total mess, like C++. Java and C# gave us some interesting and subtle lessons ab…

>C# generics have some downright nasty interactions with other parts of the type system, like operator overloading.

Operators are static methods so why is that surprising or nasty?

Re: How generics are implemented in Go 1.18

#55
post #37
post #31

Earlier quoted context omitted.

The original plan was to release in February, but in the Beta 2 release [1], they said this: "Because we are taking the time to issue a second beta, we now expect that the Go 1.18 release candidate will be issued in February, with the final Go 1.18 release in March." It looks like there are still a few release blockers [2]. I'd imagine RC is fairly soon though. EDIT: as mentioned by _fz_ below, RC1 has already releas…

> I'd imagine RC is fairly soon though. RC1 was released two weeks ago.

Well, not quite 2 weeks ago; it'll be 2 weeks on Thursday. I say this because policy is to issue a release "no sooner than two weeks after" issuing the release candidate.

https://go.dev/s/release

Re: How generics are implemented in Go 1.18

#56
post #11

Earlier quoted context omitted.

The compile time issues for C++ are entirely because of the creaky header mechanism that doesn't permit efficient parsing. Generics have worked fine in Ada since its inception. Any modern language can adopt the same process of tracking a formal abstract interface that is parsed once and expanded into concrete code as necessary.

The process of expanding genetic code into concrete code based on the types (monomorphizing) can also be an expensive process. At least, people in the rust world point to it a lot as a reason why some crates compile slowly. Monomorphizing multiplicatively increase how much code LLVM needs to process (and optimize). Mind you, C/C++’s ridiculous header system is probably still a much bigger issue. Especially because C+…

> Mind you, C/C++’s ridiculous header system is probably still a much bigger issue. Especially because C++ templates usually need to go in header files.

IDK about that. A project I'm working on is template-heavy in a major way, entirely header-only (~15kloc of this: https://github.com/celtera/avendish/blob/main/include/avnd/c... more or less) but with a barely correctly set-up dev environment with clang and PCH (a couple lines in CMake), ninja and mold, individual rebuilds are pretty much instant ; a complete rebuild which on my machine builds 49 libraries and 38 executables takes a whopping 7 seconds, CMake included.

Re: How generics are implemented in Go 1.18

#57
post #52
post #42

Earlier quoted context omitted.

Rust does compile slower than Go, but it's not due to generics. It's mostly due to LLVM codegen and procedural macros. Go has the benefit of not relying on LLVM and not having procedural macros.

Absolutely true. I’d add that Rust is also doing a lot more expensive optimizations in release builds.

Until recently Go didn't even use registers for passing arguments, it just put everything on the stack like in a 1965 textbook (https://go.googlesource.com/proposal/+/refs/changes/78/24817...)

Re: How generics are implemented in Go 1.18

#58
post #50
post #47

Programming languages are lacking because they are too stuck in the "implementation plane" while trying to deal with lots of "system design" problems. Generics, traits, interfaces, union types and others are fundamentally targeted at giving developers more expressive power to describe the systems we are designing. We know there are many parts we could swap around, using different implementations, connecting some piec…

Right. Basically Go team is lacking big picture thinkers like this[1] 1. https://dilbert.com/strip/1994-12-17

Go generics were designed with plenty of cooperation from the PL research community. While some complexity to the design may be unavoidable, it's the farthest thing from just having a hacked-together feature with no "big picture" thinking underneath. Very similar to how generics were added to Java, in fact/

Re: How generics are implemented in Go 1.18

#59
post #52

Earlier quoted context omitted.

Absolutely true. I’d add that Rust is also doing a lot more expensive optimizations in release builds.

Until recently Go didn't even use registers for passing arguments, it just put everything on the stack like in a 1965 textbook ( https://go.googlesource.com/proposal/+/refs/changes/78/24817... )

If you mean for function calls, I believe you're correct, not taking into account inline functions.

However, for code generation Go obviously uses registers since way before the 1.0 days.

Re: How generics are implemented in Go 1.18

#60
post #54

Earlier quoted context omitted.

I only occasional do language design / compiler writing projects, or work with compiler internals. Most people are really bad at estimating the implementation complexity and tradeoffs inherent in various language features. I'd say that C++ serves as a warning to others... think before you add features to your language, or you'll end up a total mess, like C++. Java and C# gave us some interesting and subtle lessons ab…

>C# generics have some downright nasty interactions with other parts of the type system, like operator overloading. Operators are static methods so why is that surprising or nasty?

It affects method overloading too, I should have said “method overloading”.

Just take a look at the rules for method overloading in C#, or take a look at one of the various C# compilers to see how methods are resolved.

Post reply on HN