Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec: provide some way to refer to a generic function without instantiation #52654

Open
josharian opened this issue May 2, 2022 · 10 comments
Open
Labels
generics Issue is related to generics NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@josharian
Copy link
Contributor

The motivation behind type aliases was the ability to refer under a new name to a thing that exists elsewhere. Prior to generics, functions can be easily re-referred to using assignment:

var Cut = strings.Cut

However, doing the same thing with a generic function fails with error message "cannot use generic function F without instantiation". It is possible to define a wrapper function, but that requires copy/pasting the entire function signature.

It'd be nice if the plain assignment worked.

I understand that this probably raises non-trivial spec difficulties. I just wanted to flag it as a useful thing.

I imagine this is a dupe, but I couldn't find it.

cc @ianlancetaylor @dsnet

@josharian josharian added the generics Issue is related to generics label May 2, 2022
@randall77
Copy link
Contributor

Related, #46477

@ianlancetaylor
Copy link
Contributor

CC @griesemer

@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 2, 2022
@ianlancetaylor ianlancetaylor added this to the Backlog milestone May 2, 2022
@griesemer
Copy link
Contributor

A variable to which an uninstantiated generic functions is assigned would need generic function type. Presumably a different generic function (with the same signature) could be assigned to that variable. One would need to be able to instantiate and invoke the generic function stored in that variable. I'm not sure that we know how to do this (if we can, we could probably also have type parameters on methods). I think the spec changes and type checking would be fairly straight-forward; the problems seem to be on the implementation/translation side.

An alias mechanism for functions might be more tenable, but we don't have anything like this yet.

@Jorropo
Copy link
Member

Jorropo commented May 3, 2022

How would:

var Clip = slices.Clip

func init() {
  impl := os.Getenv("IMPLEMENTATION")
  if impl != "" {
    var ok bool
    Clip, ok = implementations[impl]
    if !ok {
      panic(fmt.Errorf("Implementation %q not found", impl))
    }
  }
}

Compile ?

I think using this instead is clearer and fixes most of the complexity issues:

const Clip = slices.Clip

@griesemer
Copy link
Contributor

A function declaration is already effectively a constant declaration with function value, except that we use func not const for clarity (using const, as "obvious" as it might be when thinking about, would probably confuse a lot of people). So if we'd go this route, we'd probably write

func Clip = slices.Clip

(same effect but making it clear that we're talking about a function). So this would be a function alias declaration.

@beoran
Copy link

beoran commented May 11, 2022

@griesemer Actually, the general concept of function aliases with the syntax you propose would be useful for non generic functions as well. So I am in favor of this.

@randall77
Copy link
Contributor

randall77 commented Jun 23, 2022

Function aliases would also be useful for fixes like in CL 211617.

var ExportedF = localF

Calls to ExportedF can't be analyzed by escape analysis, as ExportedF might be reassigned. We instead need to do

func ExportedF(arg1 T1, arg2 T2) R { return localF(arg1, arg2) }

It would be nice to be able to do

func ExportedF = localF

In which case ExportedF can't be reassigned, so escape analysis can be sure of the target of an ExportedF call.

@jsternberg
Copy link

This also appears to impact type aliases which makes it seem like it's not possible to type alias generic types.

https://go.dev/play/p/HwjOUsIfmhq

I'll get this error when I attempt to run the code:

package main

import "fmt"

type A[T any] struct {
	V T
}

func (a *A[T]) Value() T {
	return a.V
}

type B = A

func main() {
	a := &B[int]{V: 2}
	fmt.Println(a.Value())
}
./prog.go:15:10: cannot use generic type A[T any] without instantiation

@esimov
Copy link

esimov commented Sep 10, 2022

I was searching for a solution to assign a generic type struct to a variable defined on the package level but without instantiating the generic struct with a concrete type, but it seems like that this is not really possible at the moment. This would be needed for example when we would like to instantiate a new struct only once like in the singleton pattern. The most straightforward way would be to guard the struct instantiation with a local variable which holds the generic struct type. But this unfortunately is not possible.

type node[T any] struct {
	data T
	next *node[T]
}

var once sync.Once
var n = node /// <== error: cannot use generic type without instantiation. 

func NewNode[T any](data T) *node[T] {
	once.Do(func() {
		n = &node[T]{
			data: data,
			next: &node[T]{},
		}
	})
	return n
}

@Merovius
Copy link
Contributor

Merovius commented Jul 20, 2023

FWIW I found this issue because I'm genuinely curious about use-cases for this that are not solved by the function-alias idea discussed above. I understand why we don't allow it (yet) and it seems the primary blocker for having generic methods to me. But I'd be interested in use cases for the feature of allowing to pass around uninstantiated functions/types itself.

@esimov In your code, what would this do?

func main() {
    n1 := yourpkg.NewNode(42)
    n2 := yourpkg.NewNode("foobar")
    fmt.Printf("%T, %T, %#v, %#v", n1, n2, n1, n2)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
generics Issue is related to generics NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

9 participants