2

Given the current type parameter proposal (I don't expect it to change significantly) I want to write an interface constraint that limits struct types to those that embed another struct.

The idea is:

type Base struct {}

type Foo struct { Base }

type Bar struct { Base; s string }

type Baz struct { s string }

func fn[T HasBase](v T) {
    // ...
}

The fn function should be instantiated with Foo and Bar but not with Baz. The purpose would be to access Base (and its fields) from the function body, and possibly enforcing some particular type composition in API design.

I could try with the following:

type HasBase interface {
    ~struct{ Base }
}

where HasBase is defined as the type set of types whose underlying type is struct{ Base }.

Given that the underlying type of a struct literal is itself, this HasBase allows Foo but not Bar.

I could add Bar's underlying type to the constraint:

type HasBase interface {
    ~struct{ Base } | ~struct{ Base; s string }
}

But this is not scalable. I need to match the structs definitions literally, even the field names must match. Even worse, although the proposal hints that the above is possible, it was actually left out of the implementation.

So based on the linked issue I can use the following workaround, i.e. declare a method on the Base type (possibly unexported) and throw that into the type constraint:

func (b Base) getBase() Base { return b }

type HasBase interface {
    getBase() Base
}

which isn't much different than using HasBase as a simple non-constraint interface (!!) and forgo generics — probably differing only in interface boxing of non-pointer types?

// also works, and also gives access to the getBase() method
func fn2(t HasBase) {
    // ...
}

Am I missing something obvious, or is this actually the only way to do this as of today?

GoTip playground: https://gotipplay.golang.org/p/_SlZlnDL1dE

blackgreen
  • 34,072
  • 23
  • 111
  • 129
  • _"The purpose would be to access Base (and its fields) from the function body."_ Then `fn()` should take a value of `Base` simply. – icza Dec 02 '21 at 10:50
  • @icza true actually, although I envision the constraint could be useful for enforcing some particular type composition in API design – blackgreen Dec 02 '21 at 10:57
  • 2
    Reading through the proposal, I don't think you're missing anything. Primary design of constraints is to restrict the type set for specific operations, having a field in a struct does not fall under this category. – icza Dec 02 '21 at 13:34

0 Answers0