8000 proposal: spec: type inference for union of functions · Issue #61802 · golang/go · GitHub 8000
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
proposal: spec: type inference for union of functions #61802
Open
@matthewmueller

Description

@matthewmueller

Context

Type inference is a powerful feature where Go can infer generic types based on usage. In the following example, the RPC(Hello) function is able to infer types based on the function signature.

func RPC[In, Out any, Fn Func[In, Out]](fn Fn) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    var in In
    if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
      http.Error(w, err.Error(), http.StatusBadRequest)
      return
    }
    out, err := fn(&in)
    if err != nil {
      http.Error(w, err.Error(), http.StatusInternalServerError)
      return
    }
    if err := json.NewEncoder(w).Encode(out); err != nil {
      http.Error(w, err.Error(), http.StatusInternalServerError)
      return
    }
  })
}

type HelloIn struct {
}

type HelloOut struct {
}

func Hello(in *HelloIn) (*HelloOut, error) {
  return &HelloOut{}, nil
}

// Usage
mux := http.NewServeMux()
mux.Handle("/hello", RPC(Hello))

The long-form equivalent is RPC[HelloIn, HelloOut](Hello). This also works with type constraints when you have a single type. In the following example, we introduce a Func constraint:

type Func[In, Out any] interface {
  func(in *In) (*Out, error)
}

Then adjusting the RPC function to the following:

func RPC[In, Out any, Fn Func[In, Out]](fn Fn) http.Handler {
  // ...
}

And type inference continues to work as expected.

Problem

If you introduce another type like the following:

type Func[In, Out any] interface {
  func(in *In) (*Out, error) | func(ctx context.Context, in *In) (*Out, error)
}

Then type inference no longer works. You'll be greeted with:

./main.go:66:26: cannot infer In 

To fix this, you need to specify the types:

// Usage
mux := http.NewServeMux()
mux.Handle("/hello", RPC[HelloIn, HelloOut](Hello))

Proposal

It'd be great if type inference could infer more complex types. It does seem to work with basic type constraints, which is awesome:

type StringOrInt interface {
	string | int
}

func print[T StringOrInt](t T) {
	switch t := any(t).(type) {
	case string:
		println(t)
	case int:
		println(t)
	}
}

// usage
print(10) // works!
print("hello") // works!

Could this be extended to support more complex types?


Thanks for your consideration!

Metadata

Metadata

Assignees

No one assigned

    Labels

    ProposalTypeInferenceIssue is related to generic type inference

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0