What do you make of this? https://go2goplay.golang.org/p/gN-FK2kbYK5
Using interface values, it seems possible to bypass a declared constraint that two arguments have the same type. I am wondering the following. 1. If the function signature says two types should be the same (via type parameters), but this can't be determined at compile time, then a runtime check should be inserted at the call point - and panic if fail. 2. Since a nil interface value has "no type", then nil interface values should be disallowed for arguments defined with type parameters. Again, if this can't be determined statically, then add a runtime check and panic. Incidentally, point (2) also sidesteps the OP's original problem, since it guarantees the value can never be nil. On Wednesday, 20 January 2021 at 10:43:42 UTC axel.wa...@googlemail.com wrote: > On Wed, Jan 20, 2021 at 11:08 AM Brian Candler <b.ca...@pobox.com> wrote: > >> The end result is there's a crucial but subtle difference between: >> >> type Foo interface { ... } >> func f(v Foo) ... >> >> and >> >> type Foo interface { ... } >> func f[T Foo](v T) ... >> >> Given that the second case supports both concrete types *and* interface >> types, then it seems to me that comparing a value with nil is a >> semantically valid thing to do. >> > > FWIW, it's also possible to write a constraint that can *only* be > satisfied by concrete types - namely one containing a type-list. > > IMO it is confusing to allow comparing generic values to nil, in general. > If we could, I would either assume I can compare any *non*-generic value to > nil. I would assume we can always go from a generic function to an > instantiated one by substituting all occurrences of the type-parameters. > But IMO, nil is already confusing enough as it is. > > I think the solutions Patrick and Ian provided for checking if an > interface is nil, or a value is zero, are enough. Because, to be clear: > Calling a method on an interface can panic *whether or not that interface > is nil*. Fundamentally, the case where a caller passes you a nil-interface > is not different from the case where a caller passes you an interface with > a method that dereferences a nil-pointer or accesses a slice out of bounds > - or an interface that just calls panic("foo") in one of its methods. It's > a bug in the caller and panicing in such a case is the correct thing to do. > You will never be able to statically catch all bugs or statically prevent > all panics. I don't think this particular panic is special enough to give > it extra attention - because, again, you *can* do the check, if you want > to, it's just not super convenient. > > > If the function specialisation is a concrete type, then that comparison >> would always be false and the code path optimised out. >> >> Alternatively, generics could exclude interface values. But then you get >> the weird situation that a generic function declaration that *looks* like >> an interface type, explicitly disallows interface type values! >> >> ---- 8< ---- >> >> With my wild hat on: it makes me wonder what would happen if the generics >> proposal became nothing more than interfaces with linked constraints - so >> that you could say "this function takes a function of type T (interface C) >> and returns *the same type* T", or "this function takes a []T and returns a >> value of *the same type* T". >> >> What I mean is, the difference between >> func f(a, b fmt.Stringer) c fmt.Stringer { ... } >> and >> func f[T fmt.Stringer](a, b T) c T { ... } >> would simply be that a, b and c had to be of the *same* concrete type - >> but were otherwise still interface values (and specialisation, if >> implemented, would just be a hidden optimisation). >> >> The obvious problem is that if you actually pass interface values around, >> then many type-mismatch violations couldn't be detected until runtime. >> >> However: I find the same problem occurs with the current generics >> implementation, *if* you pass interface variables. Check this out: >> https://go2goplay.golang.org/p/F08gh5gotsO >> Print2() expects that both arguments are of the same type - but in the >> final call, they are not! There is neither compile-time nor run-time error. >> >> ISTM that constrained interface types *could* also be checked at compile >> time, in the common case where the caller passes concrete types. Rewriting >> to use plain interfaces instead of generics: >> https://go2goplay.golang.org/p/CfkvAcgr8mC >> I think that an interface type constraint system *could* statically check >> that both args of the first Print2() call were (or were not) the same type. >> >> What you might end up with is linked type constraints being a natural >> extension of interfaces. Generic specialisation would just be an >> optimisation on top of that (if the call site knows that a particular set >> of concrete types is being used). Type lists could also become an >> extension of interfaces. >> >> However, that's just off the top of my head. Whilst I've been following >> generics intermittently, no doubt this has been considered (and discarded) >> before. >> >> Regards, Brian. >> >> -- >> 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...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/34bdb40e-ad0b-47ce-8588-d014d0886470n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/34bdb40e-ad0b-47ce-8588-d014d0886470n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e4e446de-9be4-4e31-8df7-ed48998022een%40googlegroups.com.