When a generic function converts a shape-typed value to an interface
and then type-asserts or type-switches on it, some cases can never
match because the asserted concrete type has a different shape than
the source. For example:
func foo[S string | []byte](x S) {
switch any(x).(type) {
case string: // possible only when S has shape string
case []byte: // possible only when S has shape []uint8
}
}
Since instantiated generic funcs work on shapes, all instantiations
contain the code for all cases even if they will never be hit.
Detect OCONVIFACE of a shape type followed by a concrete type
assertion, and compare the shapes. If they are incompatible, the
assertion can never succeed for that instantiation.
This applies to both type switch cases (which are skipped entirely)
and comma-ok type assertions (which are replaced with zero, false).
The analysis also tracks through intermediate variables using a
pre-walk pass with ReassignOracle, so patterns like
iface := any(x)
v, ok := iface.(string)
are handled as well.
Updates #57072
Change-Id: I837f6089b9e431f856a528463075fd10abe464dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/767640
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>