On Mon, Jul 6, 2020 at 6:29 PM, roger peppe <rogpe...@gmail.com> wrote:

>
> I've also been playing around in this area. I've been trying something
> similar to this approach: https://go2goplay.golang.org/p/sHko_EMhJjA
> But this isn't ideal - note that we lose type safety when assigning back
> to the generic hash function, because there's no way to let the compiler
> know that the actual type of the generic type parameter is known at that
> point.
>
> I also noticed an interesting wrinkle to doing a type switch on a value of
> the type:
>
> We can't do this:
>
>   case Hasher:
>       hi = func(t Hasher) uintptr {
>           return t
>       }
>
> because the actual type probably isn't Hasher - it's the actual type, not
> the interface type.
>
> If a type switch on a type argument was implemented (and I definitely
> support it) we'd have to think carefully about what semantics would be
> desired in this case - if one of the types is an interface type, would one
> get the usual interface-subtype rules for matching or not?
>
> For the record, I quite like the idea of using a separate syntax for
> type-based checking:
>
>    type switch T {
>    case int:
>    case string:
>    }
>
> That way, we could use exact-match rules for that construct without risk
> of confusion with the normal type switch rules, and perhaps the difference
> might make it clearer that T would change its type inside the body of the
> switch.
>
If the idea is to be able to refine the constraints on a type parameter,
then you need to be able to match based on "T satisfies this interface". If
you want to be able to match based on underlying type, you could match
against e.g. interface { type int }.

I'm not sure how useful matching on a precise type is in this context.
Interfaces can't express exact type constraints as currently designed, so
exact type matching can't ever handle all cases. You'd need a really good
reason to be treating exactly one type out of the set with the same
underlying type differently in order for it to make sense.

If you needed to, though, you could plausibly do it by:

type switch *T {
case interface { type *fmt.Stringer }:
        // T has to be the interface type `fmt.Stringer`
case interface { type *int }:
        // T has to be the specific concrete type `int`
}

Whether to support the following is what could potentially cause confusion:

func F(type T interface { type int })(t T) {
    type switch T {
    case int:
        ...
    }
}

Someone could plausibly believe this covers all possible cases, when it
doesn't cover type MyInt int, for example. This could either be disallowed
or picked up by a lint. Disallowing it would force the above workaround
syntax using pointer types in interface type lists. This is a bit kludgey,
but then it probably shouldn't be easier to do the thing which will more
often be wrong than the thing that will more often be right.

The other thing is that interface constraints as currently designed don't
really lend themselves to refinement in the first place. Sure, if you have
an interface with a type list, you can match on a subset of that type list,
but you can't ask whether a type "is in this type list *or* satisfies this
interface" or "satisfies at least one interface in this list". Easiest
solution might be to allow comma separated embedded interfaces:

type CustomOrdered(type T) interface {
    Less(T) bool
}

type AnyOrdered(type T) interface {
    constraints.Ordered, (CustomOrdered(T))
}

(I should also mention I don't really *like* having to define the
above interfaces so they have to be applied reflexively to work. The
fact that it will be done automatically in type parameter lists helps,
but it still feels wrong to have to do it. I understand that this is
to sidestep needing to add a second kind of generic type name in
interface definitions, though.)

-- 
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/CANjmGJtp8osgT1xxPz-DdT9DF0c7-sWny2N9Ad60dFGLwUmadw%40mail.gmail.com.

Reply via email to