Skip to content

cmd/compile: better optimization of type switches in instantiated generic functions #59591

@ianlancetaylor

Description

@ianlancetaylor

Consider this test case:

package main

import (
	"fmt"
	"unsafe"
)

func start[S []byte | string](s S) *byte {
	switch s := any(s).(type) {
	case []byte:
		return unsafe.SliceData(s)
	case string:
		return unsafe.StringData(s)
	default:
		panic("can't happen")
	}
}

func F[S []byte | string](s S) {
	fmt.Println(start(s), len(s))
}

func main() {
	F("hi")
	F([]byte("bye"))
}

This runs fine. It instantiates F twice: main.F[go.shape.[]uint8] and main.F[go.shape.string]. Both versions take a dictionary, and both versions implement the type switch by loading the type descriptor from the dictionary and comparing it to the descriptors for []byte and string.

In these instantiations, however, the type descriptor is a constant. We know this because the constraint does not use a ~. It would be nice if the compiler were able to constant fold the dictionary value and eliminate the type switch.

I came up with this example because of #38776. It would be nice if we could change some of the hash implementations to use generic functions, which largely works until they try to call assembly code. At that point it's necessary to get the pointer to the slice or string data. It would be nice to be able to do that reasonably safely, which is what the above code does, and also efficiently, which the above code is not.

CC @randall77 @mdempsky

Metadata

Metadata

Assignees

Labels

FeatureRequestIssues asking for a new feature that does not need a proposal.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

In Progress

Relationships

None yet

Development

No branches or pull requests

Issue actions