Home  >  Article  >  Backend Development  >  Unable to infer types in generic parameters of function constructor

Unable to infer types in generic parameters of function constructor

PHPz
PHPzforward
2024-02-09 08:00:32642browse

Unable to infer types in generic parameters of function constructor

php editor Youzi will answer a common question for everyone: the reason why the type cannot be inferred from the generic parameters of the constructor. In PHP, type inference for generic parameters is achieved through the default value of the parameter. However, in a constructor, since the parameters are passed in before the object is created, the type of the parameters cannot be inferred from the object's instance. This results in the inability to infer the type of the generic parameter in the constructor, and the type needs to be manually specified to solve this problem.

Question content

I have some generic code in go where I have a "master" type with a generic parameter and many "slave" types that should share the same generic parameters. The code looks similar to this:

type Doer[T any] interface {
    ModifyA(*A[T])
}

type B[T any] struct {
}

func NewB[T any]() *B[T] {
    return new(B[T])
}

func (b *B[T]) ModifyA(a *A[T]) {
    // Do a thing
}

type A[T any] struct{}

func NewA[T any]() A[T] {
    return A[T]{}
}

func (a *A[T]) Run(doers ...Doer[T]) {
    for _, doer := range doers {
        doer.ModifyA(a)
    }
}

func main() {
    a := new(A[int])
    a.Run(NewB())   // error here
}

Basically, the user should define t on a and then t on b should be the same. This type of code works in other languages ​​that support generics, but in go I get a cannot infer t compile error at the commented line (see the go playground code here). It seems to me that the type parameter on a is set to int , so the type parameter on b should also be set to int . I could call newb[int]() instead, but that seems too verbose to me. Why does this happen?

Solution

This is a variation on "Why can't the compiler infer the type parameters based on how the return type is used?" Answer: Because as of go 1.20, this is not how type inference works.

Type inferenceApplies to:

  • Type parameter list
  • Replacement map m initialized with known type parameters (if any)
  • A (possibly empty) list of ordinary function parameters (only in the case of function calls)

If you check these rules one by one:

  • newb() Is there a type parameter list? No. You didn't specify a type parameter when calling it.

  • Are there other known type parameters that can be used to infer other type parameters? No, you didn't provide any type parameters at all. Note that this case applies to function calls where you provide a partial number of type parameters, for example:

    func foo[T any, U *T]() {}

    In the above you can only provide t, for example float64, the compiler will construct the replacement map using t -> float64 and then infer u -> *float64

  • Finally, is there a list of normal function parameters? no. newb is empty.

That’s all. The compiler does not infer type parameters based on how the function's return type is used.

At the time of writing, relevant proposals under discussion are:

The above is the detailed content of Unable to infer types in generic parameters of function constructor. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete