uber-go/fx

Annotation: Param/ResultTags with In/Out

sywhang opened this issue · 7 comments

Currently, fx.ParamTags and fx.ResultTags error out when they're used with fx.In and fx.Out.

It makes sense that fx.ParamTags shouldn't be used with fx.In, and fx.ResultTags with fx.Out, but there's no reason for fx.ParamTags to not be able to be used with fx.Out.

We should allow the usage of fx.ParamTags annotation with fx.Out, and similarly, fx.ResultTags with fx.In.

recht commented

Related to this, if I have a constructor that takes two args, the second of them being an fx.In struct, but I want to put a ParamTags on the first one then that's also not possible, which also seems overly restrictive.

Thanks for the feedback @recht. We can also look into making that possible.

EDIT: Disregard. I misread.

I think there may be some annoying cases with supporting ParamTags on fx.In.

type Foo struct{ fx.In; /* ... */ }
type Bar struct{ fx.In; /* ... */ }

func New(Foo, Bar) *Baz { ... }

This is valid. If ParamTags supports fx.In structs, then the position of ParamTags has to match the fields of Foo first, and Bar next.

This is also valid:

type Foo struct { fx.In; /* ... */ }

type Bar struct{
  fx.In

  Foo Foo
}

func New(Bar) *Baz

In this case, ParamTags will have to recurse down.

These are both possible but annoying. I suggest moving support for those into a separate ticket, and scoping this to just allowing ParamTags with fx.Out, and ResultTags with fx.In.

@abhinav Perhaps I misunderstood, but isn't @recht's request that we be able to annotate types with fx.ParamTags when they're not an fx.In struct? i.e.

type Foo struct {
  // not an fx.In struct
}

type Bar struct {
  fx.In
  // stuff
}

func New(Foo, Bar) FooBar { ... }

fx.Provide(
  New,
  fx.ParamTags(`name:"myFoo"`),
)

Oops, you're right. I misread.

@jkanywhere reported this issue as well. We'll have someone take a look at this

@JacobOaks if you're looking for another Fx issue to handle, this may be a good one.