exhaustive icon indicating copy to clipboard operation
exhaustive copied to clipboard

missing diagnostics for switch statements that switch on a type parameterized type

Open nishanths opened this issue 3 years ago • 2 comments

It is unclear to me at this point what effect the upcoming go1.18 type parameter change will have on this analyzer. We may need to define the analyzer's behavior when type parameters are involved. The analzyer implementation may also need to be updated to handle type parameters.

nishanths avatar Nov 16 '21 06:11 nishanths

now that 1.18 is out, does anyone know if this still works?

ghostsquad avatar Jun 02 '22 21:06 ghostsquad

It continues to work if the switch statement doesn't switch on a type-parameterized type.

However, if the switch statements switches on a type-parameterized type, exhaustive fails to detect missing cases. For example, for the switch statement in the function foo below, I think it should have reported missing B. In bar, I think it should have reported missing B and C.

package typeparam

type M int

const (
	A M = iota
	B
)

type N uint

const (
	C N = iota
	D
)

func foo[T M](v T) {
	switch v {
	case T(A):
	}
}

func bar[T M | N](v T) {
	switch v {
	case T(A):
	case T(D):
	}
}

One of the issues that should be addressed is that exhaustive doesn't check these switch statement because of an early-out return in switch.go.

https://github.com/nishanths/exhaustive/blob/c85349aae7e274d7dff96331a1f20481ba8ce157/switch.go#L94-L99

(The type is *types.TypeParam, not *types.Named, for the example above.)

nishanths avatar Jun 03 '22 05:06 nishanths

Work-in-progress definition of the analyzer's behavior for type parameters.

Initial version

# Type parameters

A switch statement that switches on a value whose type is a type
parameter is checked for exhaustiveness iff each term of the type
constraint is an enum type. The following switch statement will be
checked, assuming M, N, and O are enum types. To satisfy exhaustiveness,
all enum members for each of M, N, and O must be listed in the switch
statement's cases.

	func bar[T M | I](v T) {
		switch v {
		}
	}

	type I interface {
		N | O
	}

Update 1

# Type parameters

A switch statement that switches on a value whose type is a type parameter is
checked for exhaustiveness iff each type element in the type constraint is
an enum type and shares the same underlying basic kind. For example, the
following switch statement will be checked, assuming M, N, and O are enum
types with the same underlying basic kind. To satisfy exhaustiveness, all enum
members for each of the types M, N, and O must be listed in the switch
statement's cases.

	func bar[T M | I](v T) {
		switch v {
		}
	}
	type I interface{ N | J }
	type J interface{ O }

nishanths avatar Nov 24 '22 21:11 nishanths