As for me then everything is much more simple if Go language (as the starting point) will introduce a non-reified generics. Non reified generics does not requires a complex runtime support (static code which was generated by the compiler will be enough). Type checking of the type arguments performed at the compile time on the calller side (sender code). The callee side (receiver code) remains unchanged as it is currently is. This has some benefits: 1. This is a starting point (but not a no dead end) and point for a later enhancements 2. Does not requires significant changes in the compiler (codegen) 3. Does not requires significant changes in the runtime (engine) 4. Does not requires significant changes in the type system (just to add a few additional fields into the interface type presentation) 5. Does not requires significant changes in the reflection (just to adapt for slightly extended type presentation)
Because they (generic types) will be not reified on the callee side (receiver code) then compiler can generate the same code as it generates currently. Only callers side will perform generic type checks before assignments of values with generic types and vice versa (to variables, constants, function and methods arguments). That is. type Foo<K, V> struct { } func (s *Foo) Get(key K) (val V) { // Here is generated unchanged code // The same as for non generic use } func some() { foo := Foo<string, int>{} // Generated by the compiler // _typ := _getRTypeOf(foo) // _typ.isGeneric = true // _typ.genParams = [2]_GenParam // _typ.genParams[0] = &_GenParam{key: "K", val: _getRType(interface{}} // _typ.genParams[0] = &_GenParam{key: "V", val: _getRType(interface{}} // _typ.genArgs = [2]*_RType{} // _typ.genArgs[0] = _getRType(string) // _typ.genArgs[1] = _getRType(int) // Also compiler statically performs type check bounds of the type arguments to type parameters assignments (if type bounds specified) var key interface{} key = bool // Generated by the compiler (safe guard) // _temp0 := key // _checkGenericArg(_typ, 0, temp0) // _temp1 := foo.Get(key) val := foo.Get(_temp0) } That is, the compiler always (if it cannot compute the type at compile time and cannot to check them statically) inserts "safe guards" type check before any kimd of an assignments. The `_checkGenericArg(_typ, index, key)` also performs the checks to type parameter bounds (eg. for Foo<K string, V int>) for a given index of the type parameter and argument. Callee code does not performs any type checks on incomming parameters. It always think that incomming parameters has specified type. That is, if type bounds ommitted then specified type is interface{} If type bounds specified then specified type is itself Eg. type Type1<E> struct { } type Type2<E int> struct { } func(t *Type1) foo(val E) { } func(t *Type2) foo(val E) { } Generated as the following (that's easy) func(t *Type1) foo(val interface{}) { } func(t *Type2) foo(val int) { } -- 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.