// Copyright (c) 2020-2021 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package fx

import (
	
	
	
	
	

	
	
)

// Annotated annotates a constructor provided to Fx with additional options.
//
// For example,
//
//	func NewReadOnlyConnection(...) (*Connection, error)
//
//	fx.Provide(fx.Annotated{
//	  Name: "ro",
//	  Target: NewReadOnlyConnection,
//	})
//
// Is equivalent to,
//
//	type result struct {
//	  fx.Out
//
//	  Connection *Connection `name:"ro"`
//	}
//
//	fx.Provide(func(...) (result, error) {
//	  conn, err := NewReadOnlyConnection(...)
//	  return result{Connection: conn}, err
//	})
//
// Annotated cannot be used with constructors which produce fx.Out objects.
// When used with [Supply], Target is a value instead of a constructor.
//
// This type represents a less powerful version of the [Annotate] construct;
// prefer [Annotate] where possible.
type Annotated struct {
	// If specified, this will be used as the name for all non-error values returned
	// by the constructor. For more information on named values, see the documentation
	// for the fx.Out type.
	//
	// A name option may not be provided if a group option is provided.
	Name string

	// If specified, this will be used as the group name for all non-error values returned
	// by the constructor. For more information on value groups, see the package documentation.
	//
	// A group option may not be provided if a name option is provided.
	//
	// Similar to group tags, the group name may be followed by a `,flatten`
	// option to indicate that each element in the slice returned by the
	// constructor should be injected into the value group individually.
	Group string

	// Target is the constructor or value being annotated with fx.Annotated.
	Target interface{}
}

func ( Annotated) () string {
	var  []string
	if len(.Name) > 0 {
		 = append(, fmt.Sprintf("Name: %q", .Name))
	}
	if len(.Group) > 0 {
		 = append(, fmt.Sprintf("Group: %q", .Group))
	}
	if .Target != nil {
		 = append(, fmt.Sprintf("Target: %v", fxreflect.FuncName(.Target)))
	}
	return fmt.Sprintf("fx.Annotated{%v}", strings.Join(, ", "))
}

var (
	// field used for embedding fx.In type in generated struct.
	_inAnnotationField = reflect.StructField{
		Name:      "In",
		Type:      reflect.TypeOf(In{}),
		Anonymous: true,
	}
	// field used for embedding fx.Out type in generated struct.
	_outAnnotationField = reflect.StructField{
		Name:      "Out",
		Type:      reflect.TypeOf(Out{}),
		Anonymous: true,
	}
)

// Annotation specifies how to wrap a target for [Annotate].
// It can be used to set up additional options for a constructor,
// or with [Supply], for a value.
type Annotation interface {
	apply(*annotated) error
	build(*annotated) (interface{}, error)
}

var (
	_typeOfError = reflect.TypeOf((*error)(nil)).Elem()
	_nilError    = reflect.Zero(_typeOfError)
)

// annotationError is a wrapper for an error that was encountered while
// applying annotation to a function. It contains the specific error
// that it encountered as well as the target interface that was attempted
// to be annotated.
type annotationError struct {
	target interface{}
	err    error
}

func ( *annotationError) () string {
	return .err.Error()
}

// Unwrap the wrapped error.
func ( *annotationError) () error {
	return .err
}

type paramTagsAnnotation struct {
	tags []string
}

var _ Annotation = paramTagsAnnotation{}
var (
	errTagSyntaxSpace            = errors.New(`multiple tags are not separated by space`)
	errTagKeySyntax              = errors.New("tag key is invalid, Use group, name or optional as tag keys")
	errTagValueSyntaxQuote       = errors.New(`tag value should start with double quote. i.e. key:"value" `)
	errTagValueSyntaxEndingQuote = errors.New(`tag value should end in double quote. i.e. key:"value" `)
)

// Collections of key value pairs within a tag should be separated by a space.
// Eg: `group:"some" optional:"true"`.
func verifyTagsSpaceSeparated( int,  string) error {
	if  > 0 &&  != "" && [0] != ' ' {
		return errTagSyntaxSpace
	}
	return nil
}

// verify tag values are delimited with double quotes.
func verifyValueQuote( string) (string, error) {
	// starting quote should be a double quote
	if [0] != '"' {
		return "", errTagValueSyntaxQuote
	}
	// validate tag value is within quotes
	 := 1
	for  < len() && [] != '"' {
		if [] == '\\' {
			++
		}
		++
	}
	if  >= len() {
		return "", errTagValueSyntaxEndingQuote
	}
	return [+1:], nil
}

// Check whether the tag follows valid struct.
// format and returns an error if it's invalid. (i.e. not following
// tag:"value" space-separated list )
// Currently dig accepts only 'name', 'group', 'optional' as valid tag keys.
func verifyAnnotateTag( string) error {
	 := 0
	 := map[string]struct{}{"group": {}, "optional": {}, "name": {}}
	for ;  != ""; ++ {
		if  := verifyTagsSpaceSeparated(, );  != nil {
			return 
		}
		 := 0
		if strings.TrimSpace() == "" {
			return nil
		}
		// parsing the key i.e. till reaching colon :
		for  < len() && [] != ':' {
			++
		}
		 := strings.TrimSpace([:])
		if ,  := []; ! {
			return errTagKeySyntax
		}
		,  := verifyValueQuote([+1:])
		if  != nil {
			return 
		}
		 = 
	}
	return nil
}

// Given func(T1, T2, T3, ..., TN), this generates a type roughly
// equivalent to,
//
//   struct {
//     fx.In
//
//     Field1 T1 `$tags[0]`
//     Field2 T2 `$tags[1]`
//     ...
//     FieldN TN `$tags[N-1]`
//   }
//
// If there has already been a ParamTag that was applied, this
// will return an error.
//
// If the tag is invalid and has mismatched quotation for example,
// (`tag_name:"tag_value') , this will return an error.

func ( paramTagsAnnotation) ( *annotated) error {
	if len(.ParamTags) > 0 {
		return errors.New("cannot apply more than one line of ParamTags")
	}
	for ,  := range .tags {
		if  := verifyAnnotateTag();  != nil {
			return 
		}
	}
	.ParamTags = .tags
	return nil
}

// build builds and returns a constructor after applying a ParamTags annotation
func ( paramTagsAnnotation) ( *annotated) (interface{}, error) {
	,  := .parameters()
	,  := .currentResultTypes()

	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 = ()
		return .Call()
	})
	return .Interface(), nil
}

// parameters returns the type for the parameters of the annotated function,
// and a function that maps the arguments of the annotated function
// back to the arguments of the target function.
func ( paramTagsAnnotation) ( *annotated) (
	 []reflect.Type,
	 func([]reflect.Value) []reflect.Value,
) {
	 := reflect.TypeOf(.Target)
	 = make([]reflect.Type, .NumIn())
	for  := 0;  < .NumIn(); ++ {
		[] = .In()
	}

	// No parameter annotations. Return the original types
	// and an identity function.
	if len(.tags) == 0 {
		return , func( []reflect.Value) []reflect.Value {
			return 
		}
	}

	// Turn parameters into an fx.In struct.
	 := []reflect.StructField{_inAnnotationField}

	// there was a variadic argument, so it was pre-transformed
	if len() > 0 && isIn([0]) {
		 := [0]

		for  := 1;  < .NumField(); ++ {
			 := .Field()
			 := reflect.StructField{
				Name: .Name,
				Type: .Type,
				Tag:  .Tag,
			}
			if -1 < len(.tags) {
				.Tag = reflect.StructTag(.tags[-1])
			}

			 = append(, )
		}

		 = []reflect.Type{reflect.StructOf()}
		return , func( []reflect.Value) []reflect.Value {
			 := [0]
			[0] = reflect.New().Elem()
			for  := 1;  < .NumField(); ++ {
				[0].Field().Set(.Field())
			}
			return 
		}
	}

	for ,  := range  {
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: ,
		}
		if  < len(.tags) {
			.Tag = reflect.StructTag(.tags[])
		}

		 = append(, )
	}

	 = []reflect.Type{reflect.StructOf()}
	return , func( []reflect.Value) []reflect.Value {
		 := [0]
		 = [:0]
		for  := 0;  < .NumIn(); ++ {
			 = append(, .Field(+1))
		}
		return 
	}
}

// ParamTags is an Annotation that annotates the parameter(s) of a function.
//
// When multiple tags are specified, each tag is mapped to the corresponding
// positional parameter.
// For example, the following will refer to a named database connection,
// and the default, unnamed logger:
//
//	fx.Annotate(func(log *log.Logger, conn *sql.DB) *Handler {
//		// ...
//	}, fx.ParamTags("", `name:"ro"`))
//
// ParamTags cannot be used in a function that takes an fx.In struct as a
// parameter.
func ( ...string) Annotation {
	return paramTagsAnnotation{}
}

type resultTagsAnnotation struct {
	tags []string
}

var _ Annotation = resultTagsAnnotation{}

// Given func(T1, T2, T3, ..., TN), this generates a type roughly
// equivalent to,
//
//	struct {
//	  fx.Out
//
//	  Field1 T1 `$tags[0]`
//	  Field2 T2 `$tags[1]`
//	  ...
//	  FieldN TN `$tags[N-1]`
//	}
//
// If there has already been a ResultTag that was applied, this
// will return an error.
//
// If the tag is invalid and has mismatched quotation for example,
// (`tag_name:"tag_value') , this will return an error.
func ( resultTagsAnnotation) ( *annotated) error {
	if len(.ResultTags) > 0 {
		return errors.New("cannot apply more than one line of ResultTags")
	}
	for ,  := range .tags {
		if  := verifyAnnotateTag();  != nil {
			return 
		}
	}
	.ResultTags = .tags
	return nil
}

// build builds and returns a constructor after applying a ResultTags annotation
func ( resultTagsAnnotation) ( *annotated) (interface{}, error) {
	 := .currentParamTypes()
	,  := .results()
	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 := .Call()
		return ()
	})
	return .Interface(), nil
}

// results returns the types of the results of the annotated function,
// and a function that maps the results of the target function,
// into a result compatible with the annotated function.
func ( resultTagsAnnotation) ( *annotated) (
	 []reflect.Type,
	 func([]reflect.Value) []reflect.Value,
) {
	,  := .currentResultTypes()

	if  {
		 = [:len()-1]
	}

	// No result annotations. Return the original types
	// and an identity function.
	if len(.tags) == 0 {
		return , func( []reflect.Value) []reflect.Value {
			return 
		}
	}

	// if there's no Out struct among the return types, there was no As annotation applied
	// just replace original result types with an Out struct and apply tags
	var (
		       outStructInfo
		 []reflect.Type
	)

	.Fields = []reflect.StructField{_outAnnotationField}
	.Offsets = []int{}

	for ,  := range  {
		if !isOut() {
			// this must be from the original function.
			// apply the tags
			 := reflect.StructField{
				Name: fmt.Sprintf("Field%d", ),
				Type: ,
			}
			if  < len(.tags) {
				.Tag = reflect.StructTag(.tags[])
			}
			.Offsets = append(.Offsets, len(.Fields))
			.Fields = append(.Fields, )
			continue
		}
		// this must be from an As annotation
		// apply the tags to the existing type
		 := make([]reflect.StructField, .NumField())
		[0] = _outAnnotationField
		for ,  := range .tags {
			if +1 < .NumField() {
				 := .Field( + 1)
				[+1] = reflect.StructField{
					Name: .Name,
					Type: .Type,
					Tag:  reflect.StructTag(),
				}
			}
		}
		 = append(, reflect.StructOf())
	}

	 := reflect.StructOf(.Fields)

	 := []reflect.Type{}
	// append existing outs back to outTypes
	 = append(, ...)
	if  {
		 = append(, _typeOfError)
	}

	return , func( []reflect.Value) []reflect.Value {
		var (
			     error
			 []reflect.Value
		)
		 = append(, reflect.New().Elem())

		 := 0
		for ,  := range  {
			if  == len()-1 &&  {
				// If hasError and this is the last item,
				// we are guaranteed that this is an error
				// object.
				if ,  := .Interface().(error);  != nil {
					 = 
				}
				continue
			}
			if  < len(.Offsets) {
				if  := .Offsets[];  > 0 {
					// fieldIdx 0 is an invalid index
					// because it refers to uninitialized
					// outs and would point to fx.Out in the
					// struct definition. We need to check this
					// to prevent panic from setting fx.Out to
					// a value.
					[0].Field().Set()
				}
				continue
			}
			if isOut(.Type()) {
				++
				if  < len() {
					 := reflect.New([]).Elem()
					for  := 1;  < [].NumField(); ++ {
						.Field().Set(.Field())
					}
					 = append(, )
				}
			}
		}

		if  {
			if  != nil {
				 = append(, reflect.ValueOf())
			} else {
				 = append(, _nilError)
			}
		}

		return 
	}
}

// ResultTags is an Annotation that annotates the result(s) of a function.
// When multiple tags are specified, each tag is mapped to the corresponding
// positional result.
//
// For example, the following will produce a named database connection.
//
//	fx.Annotate(func() (*sql.DB, error) {
//		// ...
//	}, fx.ResultTags(`name:"ro"`))
//
// ResultTags cannot be used on a function that returns an fx.Out struct.
func ( ...string) Annotation {
	return resultTagsAnnotation{}
}

type outStructInfo struct {
	Fields  []reflect.StructField // fields of the struct
	Offsets []int                 // Offsets[i] is the index of result i in Fields
}

type _lifecycleHookAnnotationType int

const (
	_unknownHookType _lifecycleHookAnnotationType = iota
	_onStartHookType
	_onStopHookType
)

type lifecycleHookAnnotation struct {
	Type   _lifecycleHookAnnotationType
	Target interface{}
}

var _ Annotation = (*lifecycleHookAnnotation)(nil)

func ( *lifecycleHookAnnotation) () string {
	 := "UnknownHookAnnotation"
	switch .Type {
	case _onStartHookType:
		 = _onStartHook
	case _onStopHookType:
		 = _onStopHook
	}
	return 
}

func ( *lifecycleHookAnnotation) ( *annotated) error {
	if .Target == nil {
		return fmt.Errorf(
			"cannot use nil function for %q hook annotation",
			,
		)
	}

	for ,  := range .Hooks {
		if .Type == .Type {
			return fmt.Errorf(
				"cannot apply more than one %q hook annotation",
				,
			)
		}
	}

	 := reflect.TypeOf(.Target)

	if .Kind() != reflect.Func {
		return fmt.Errorf(
			"must provide function for %q hook, got %v (%T)",
			,
			.Target,
			.Target,
		)
	}

	if  := .NumOut();  > 0 {
		if  > 1 || .Out(0) != _typeOfError {
			return fmt.Errorf(
				"optional hook return may only be an error, got %v (%T)",
				.Target,
				.Target,
			)
		}
	}

	if .IsVariadic() {
		return fmt.Errorf(
			"hooks must not accept variadic parameters, got %v (%T)",
			.Target,
			.Target,
		)
	}

	.Hooks = append(.Hooks, )
	return nil
}

// build builds and returns a constructor after applying a lifecycle hook annotation.
func ( *lifecycleHookAnnotation) ( *annotated) (interface{}, error) {
	,  := .currentResultTypes()
	if ! {
		 = append(, _typeOfError)
	}

	, , ,  := .buildHookInstaller()
	if  != nil {
		return nil, 
	}

	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		// copy the original arguments before remapping the parameters
		// so that we can apply them to the hookInstaller.
		 := make([]reflect.Value, len())
		copy(, )
		 = ()
		 := .Call()
		if  {
			 := [len()-1]
			 = [:len()-1]
			if ,  := .Interface().(error);  != nil {
				// if constructor returned error, do not call hook installer
				return append(, )
			}
		}
		 := .Call(append(, ...))
		 = append(, [0])
		return 
	})
	return .Interface(), nil
}

var (
	_typeOfLifecycle = reflect.TypeOf((*Lifecycle)(nil)).Elem()
	_typeOfContext   = reflect.TypeOf((*context.Context)(nil)).Elem()
)

// validateHookDeps validates the dependencies of a hook function and returns true if the dependencies are valid.
func ( *lifecycleHookAnnotation) ( []reflect.Type,  []reflect.Type,  []reflect.Type) ( error) {
	type  struct {
		     reflect.Type
		  string
		 string
	}

	 := func( ) error {
		var  []string
		if len(.) > 0 {
			 = append(, fmt.Sprintf("name:\"%s\"", .))
		}
		if len(.) > 0 {
			 = append(, fmt.Sprintf("group:\"%s\"", .))
		}
		var  string
		if len() > 0 {
			 = fmt.Sprintf("%s `%s`", ..String(), strings.Join(, " "))
		} else {
			 = ..String()
		}
		return fmt.Errorf("the %s hook function takes in a parameter of \"%s\", but the annotated function does not have parameters or results of that type", .String(), )
	}
	 = nil
	 := make(map[]struct{})

	for ,  := range  {
		if !isIn() {
			[{: }] = struct{}{}
			continue
		}
		for  := 1;  < .NumField(); ++ {
			 := .Field()
			[{
				:     .Type,
				:  .Tag.Get("name"),
				: .Tag.Get("group"),
			}] = struct{}{}
		}
	}
	for ,  := range  {
		if !isOut() {
			[{: }] = struct{}{}
			continue
		}
		for  := 1;  < .NumField(); ++ {
			 := .Field()
			[{
				:     .Type,
				:  .Tag.Get("name"),
				: .Tag.Get("group"),
			}] = struct{}{}
		}
	}
	for ,  := range  {
		if !isIn() {
			 := {: }
			if ,  := []; ! {
				 = ()
				return
			}
			continue
		}
		for  := 1;  < .NumField(); ++ {
			 := .Field()
			 := {
				:     .Type,
				:  .Tag.Get("name"),
				: .Tag.Get("group"),
			}
			if ,  := []; ! {
				 = ()
				return
			}
		}
	}
	return
}

// buildHookInstaller returns a function that appends a hook to Lifecycle when called,
// along with the new parameter types and a function that maps arguments to the annotated constructor
func ( *lifecycleHookAnnotation) ( *annotated) (
	 reflect.Value,
	 []reflect.Type,
	 func([]reflect.Value) []reflect.Value, // function to remap parameters to function being annotated
	 error,
) {
	 = .currentParamTypes()
	,  = injectLifecycle()

	,  := .currentResultTypes()
	if  {
		 = [:len()-1]
	}

	// look for the context.Context type from the original hook function
	// and then exclude it from the paramTypes of invokeFn because context.Context
	// will be injected by the lifecycle
	 := -1
	 := -1
	 := reflect.ValueOf(.Target)
	 := reflect.TypeOf(.Target)
	 := []reflect.Type{
		_typeOfLifecycle,
	}
	for  := 0;  < .NumIn(); ++ {
		 := .In()
		if  == _typeOfContext &&  < 0 {
			 = 
			continue
		}

		if !isIn() {
			 = append(, .In())
			continue
		}
		 := []reflect.StructField{_inAnnotationField}
		for  := 1;  < .NumField(); ++ {
			 := .Field()
			if .Type == _typeOfContext &&  < 0 {
				 = 
				 = 
				continue
			}
			 = append(, )
		}
		 = append(, reflect.StructOf())

	}
	if  = .validateHookDeps(, , );  != nil {
		return
	}
	 := reflect.FuncOf(, []reflect.Type{}, false)
	 := reflect.MakeFunc(, func( []reflect.Value) ( []reflect.Value) {
		 := [0].Interface().(Lifecycle)
		 = [1:]
		 := make([]reflect.Value, .NumIn())

		 := func( context.Context) ( error) {
			// If the hook function has multiple parameters, and the first
			// parameter is a context, inject the provided context.
			if  < 0 {
				 := 0
				for  := 0;  < len(); ++ {
					if  ==  {
						[] = reflect.ValueOf()
						 = 1
						continue
					}
					if - >= 0 && - < len() {
						[] = [-]
					}
				}
			} else {
				for  := 0;  < .NumIn(); ++ {
					if  !=  {
						[] = []
						continue
					}
					 := .In()
					 := reflect.New().Elem()
					for  := 1;  < .NumField(); ++ {
						if  <  {
							.Field().Set([].Field())
						} else if  ==  {
							.Field().Set(reflect.ValueOf())
						} else {
							.Field().Set([].Field( - 1))
						}
					}
					[] = 
				}
			}
			 := .Call()
			if len() > 0 && [0].Type() == _typeOfError {
				, _ = [0].Interface().(error)
			}
			return 
		}
		.Append(.buildHook())
		return 
	})

	 := reflect.FuncOf(append(, ...), []reflect.Type{_typeOfError}, false)
	 = reflect.MakeFunc(, func( []reflect.Value) ( []reflect.Value) {
		// build a private scope for hook function
		var  *dig.Scope
		switch .Type {
		case _onStartHookType:
			 = .container.Scope("onStartHookScope")
		case _onStopHookType:
			 = .container.Scope("onStopHookScope")
		}

		// provide the private scope with the current dependencies and results of the annotated function
		 = []reflect.Value{_nilError}
		 := makeHookScopeCtor(, , )
		if  := .Provide();  != nil {
			[0] = reflect.ValueOf(fmt.Errorf("error providing possible parameters for hook installer: %w", ))
			return 
		}

		// invoking invokeFn appends the hook function to lifecycle
		if  := .Invoke(.Interface());  != nil {
			[0] = reflect.ValueOf(fmt.Errorf("error invoking hook installer: %w", ))
			return 
		}
		return 
	})
	return , , , nil
}

var (
	_nameTag  = "name"
	_groupTag = "group"
)

// makeHookScopeCtor makes a constructor that provides all possible parameters
// that the lifecycle hook being appended can depend on. It also deduplicates
// duplicate param and result types, which is possible when using fx.Decorate,
// and uses values from results for providing the deduplicated types.
func makeHookScopeCtor( []reflect.Type,  []reflect.Type,  []reflect.Value) interface{} {
	type  struct {
		     reflect.Type
		  string
		 string
	}
	 := map[]struct{}{}
	 := make([]reflect.Type, len())
	for ,  := range  {
		[] = 
		if isOut() {
			for  := 1;  < .NumField(); ++ {
				 := .Field()
				[{
					:     .Type,
					:  .Tag.Get(_nameTag),
					: .Tag.Get(_groupTag),
				}] = struct{}{}
			}
			continue
		}
		[{: }] = struct{}{}
	}

	 := []reflect.StructField{_outAnnotationField}

	 := make([][]int, len())

	for ,  := range  {
		[] = []int{}
		if isIn() {
			for  := 1;  < .NumField(); ++ {
				 := .Field()
				 := {
					:     .Type,
					:  .Tag.Get(_nameTag),
					: .Tag.Get(_groupTag),
				}

				if ,  := [];  {
					[] = append([], )
					continue
				}

				 := reflect.StructField{
					Name: fmt.Sprintf("Field%d", -1),
					Type: .Type,
					Tag:  .Tag,
				}
				 = append(, )
			}
			continue
		}
		 := {: }

		if ,  := [];  {
			[] = append([], )
			continue
		}
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: ,
		}
		 = append(, )
	}

	 = append(, reflect.StructOf())
	 := reflect.FuncOf([]reflect.Type{}, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 := len()
		 := make([]reflect.Value, )
		for  := 0;  < -1; ++ {
			[] = []
		}

		 := reflect.New([-1]).Elem()
		 := 1
		for  :=  - 1;  < len(); ++ {
			 :=  - ( - 1)
			if isIn([]) {
				 := 0
				for  := 1;  < [].NumField(); ++ {
					if len([]) > 0 && [][] ==  {
						// skip
						++
						continue
					}
					.Field().Set([].Field())
					++
				}
			} else {
				if len([]) > 0 && [][0] ==  {
					continue
				}
				.Field().Set([])
				++
			}
		}
		[-1] = 

		return 
	})
	return .Interface()
}

func injectLifecycle( []reflect.Type) ([]reflect.Type, func([]reflect.Value) []reflect.Value) {
	// since lifecycle already exists in param types, no need to inject again
	if lifecycleExists() {
		return , func( []reflect.Value) []reflect.Value {
			return 
		}
	}
	// If params are tagged or there's an untagged variadic argument,
	// add a Lifecycle field to the param struct
	if len() > 0 && isIn([0]) {
		 := [0]
		 := []reflect.StructField{
			.Field(0),
			{
				Name: "Lifecycle",
				Type: _typeOfLifecycle,
			},
		}
		for  := 1;  < .NumField(); ++ {
			 = append(, .Field())
		}
		 := reflect.StructOf()
		return []reflect.Type{}, func( []reflect.Value) []reflect.Value {
			 := [0]
			[0] = reflect.New().Elem()
			for  := 1;  < .NumField(); ++ {
				[0].Field().Set(.Field( + 1))
			}
			return 
		}
	}

	return append([]reflect.Type{_typeOfLifecycle}, ...), func( []reflect.Value) []reflect.Value {
		return [1:]
	}
}

func lifecycleExists( []reflect.Type) bool {
	for ,  := range  {
		if  == _typeOfLifecycle {
			return true
		}
		if isIn() {
			for  := 1;  < .NumField(); ++ {
				if .Field().Type == _typeOfLifecycle {
					return true
				}
			}
		}
	}
	return false
}

func ( *lifecycleHookAnnotation) ( func(context.Context) error) ( Hook) {
	switch .Type {
	case _onStartHookType:
		.OnStart = 
	case _onStopHookType:
		.OnStop = 
	}
	return 
}

// OnStart is an Annotation that appends an OnStart Hook to the application
// Lifecycle when that function is called. This provides a way to create
// Lifecycle OnStart (see Lifecycle type documentation) hooks without building a
// function that takes a dependency on the Lifecycle type.
//
//	fx.Provide(
//		fx.Annotate(
//			NewServer,
//			fx.OnStart(func(ctx context.Context, server Server) error {
//				return server.Listen(ctx)
//			}),
//		)
//	)
//
// Which is functionally the same as:
//
//	 fx.Provide(
//	   func(lifecycle fx.Lifecycle, p Params) Server {
//	     server := NewServer(p)
//	     lifecycle.Append(fx.Hook{
//		      OnStart: func(ctx context.Context) error {
//			    return server.Listen(ctx)
//		      },
//	     })
//		 return server
//	   }
//	 )
//
// It is also possible to use OnStart annotation with other parameter and result
// annotations, provided that the parameter of the function passed to OnStart
// matches annotated parameters and results.
//
// For example, the following is possible:
//
//	fx.Provide(
//		fx.Annotate(
//			func (a A) B {...},
//			fx.ParamTags(`name:"A"`),
//			fx.ResultTags(`name:"B"`),
//			fx.OnStart(func (p OnStartParams) {...}),
//		),
//	)
//
// As long as OnStartParams looks like the following and has no other dependencies
// besides Context or Lifecycle:
//
//	type OnStartParams struct {
//		fx.In
//		FieldA A `name:"A"`
//		FieldB B `name:"B"`
//	}
//
// Only one OnStart annotation may be applied to a given function at a time,
// however functions may be annotated with other types of lifecycle Hooks, such
// as OnStop. The hook function passed into OnStart cannot take any arguments
// outside of the annotated constructor's existing dependencies or results, except
// a context.Context.
func ( interface{}) Annotation {
	return &lifecycleHookAnnotation{
		Type:   _onStartHookType,
		Target: ,
	}
}

// OnStop is an Annotation that appends an OnStop Hook to the application
// Lifecycle when that function is called. This provides a way to create
// Lifecycle OnStop (see Lifecycle type documentation) hooks without building a
// function that takes a dependency on the Lifecycle type.
//
//	fx.Provide(
//		fx.Annotate(
//			NewServer,
//			fx.OnStop(func(ctx context.Context, server Server) error {
//				return server.Shutdown(ctx)
//			}),
//		)
//	)
//
// Which is functionally the same as:
//
//	 fx.Provide(
//	   func(lifecycle fx.Lifecycle, p Params) Server {
//	     server := NewServer(p)
//	     lifecycle.Append(fx.Hook{
//		      OnStop: func(ctx context.Context) error {
//			    return server.Shutdown(ctx)
//		      },
//	     })
//		 return server
//	   }
//	 )
//
// It is also possible to use OnStop annotation with other parameter and result
// annotations, provided that the parameter of the function passed to OnStop
// matches annotated parameters and results.
//
// For example, the following is possible:
//
//	fx.Provide(
//		fx.Annotate(
//			func (a A) B {...},
//			fx.ParamTags(`name:"A"`),
//			fx.ResultTags(`name:"B"`),
//			fx.OnStop(func (p OnStopParams) {...}),
//		),
//	)
//
// As long as OnStopParams looks like the following and has no other dependencies
// besides Context or Lifecycle:
//
//	type OnStopParams struct {
//		fx.In
//		FieldA A `name:"A"`
//		FieldB B `name:"B"`
//	}
//
// Only one OnStop annotation may be applied to a given function at a time,
// however functions may be annotated with other types of lifecycle Hooks, such
// as OnStart. The hook function passed into OnStop cannot take any arguments
// outside of the annotated constructor's existing dependencies or results, except
// a context.Context.
func ( interface{}) Annotation {
	return &lifecycleHookAnnotation{
		Type:   _onStopHookType,
		Target: ,
	}
}

type asAnnotation struct {
	targets []interface{}
	types   []asType
}

type asType struct {
	self bool
	typ  reflect.Type // May be nil if self is true.
}

func ( asType) () string {
	if .self {
		return "self"
	}
	return .typ.String()
}

func isOut( reflect.Type) bool {
	return (.Kind() == reflect.Struct &&
		dig.IsOut(reflect.New().Elem().Interface()))
}

func isIn( reflect.Type) bool {
	return (.Kind() == reflect.Struct &&
		dig.IsIn(reflect.New().Elem().Interface()))
}

var _ Annotation = (*asAnnotation)(nil)

// As is an Annotation that annotates the result of a function (i.e. a
// constructor) to be provided as another interface.
//
// For example, the following code specifies that the return type of
// bytes.NewBuffer (bytes.Buffer) should be provided as io.Writer type:
//
//	fx.Provide(
//	  fx.Annotate(bytes.NewBuffer, fx.As(new(io.Writer)))
//	)
//
// In other words, the code above is equivalent to:
//
//	fx.Provide(func() io.Writer {
//	  return bytes.NewBuffer()
//	  // provides io.Writer instead of *bytes.Buffer
//	})
//
// Note that the bytes.Buffer type is provided as an io.Writer type, so this
// constructor does NOT provide both bytes.Buffer and io.Writer type; it just
// provides io.Writer type.
//
// When multiple values are returned by the annotated function, each type
// gets mapped to corresponding positional result of the annotated function.
//
// For example,
//
//	func a() (bytes.Buffer, bytes.Buffer) {
//	  ...
//	}
//	fx.Provide(
//	  fx.Annotate(a, fx.As(new(io.Writer), new(io.Reader)))
//	)
//
// Is equivalent to,
//
//	fx.Provide(func() (io.Writer, io.Reader) {
//	  w, r := a()
//	  return w, r
//	}
//
// As entirely replaces the default return types of a function. In order
// to maintain the original return types when using As, see [Self].
//
// As annotation cannot be used in a function that returns an [Out] struct as a return type.
func ( ...interface{}) Annotation {
	return &asAnnotation{targets: }
}

// Self returns a special value that can be passed to [As] to indicate
// that a type should be provided as its original type, in addition to whatever other
// types it gets provided as via other [As] annotations.
//
// For example,
//
//	fx.Provide(
//	  fx.Annotate(
//	    bytes.NewBuffer,
//	    fx.As(new(io.Writer)),
//	    fx.As(fx.Self()),
//	  )
//	)
//
// Is equivalent to,
//
//	fx.Provide(
//	  bytes.NewBuffer,
//	  func(b *bytes.Buffer) io.Writer {
//	    return b
//	  },
//	)
//
// in that it provides the same *bytes.Buffer instance
// as both a *bytes.Buffer and an io.Writer.
func () any {
	return &self{}
}

type self struct{}

func ( *asAnnotation) ( *annotated) error {
	.types = make([]asType, len(.targets))
	for ,  := range .targets {
		if ,  := .(*self);  {
			.types[] = asType{self: true}
			continue
		}
		 := reflect.TypeOf()
		if .Kind() != reflect.Ptr || .Elem().Kind() != reflect.Interface {
			return fmt.Errorf("fx.As: argument must be a pointer to an interface: got %v", )
		}
		 = .Elem()
		.types[] = asType{typ: }
	}

	.As = append(.As, .types)
	return nil
}

// build implements Annotation
func ( *asAnnotation) ( *annotated) (interface{}, error) {
	 := .currentParamTypes()

	, ,  := .results()
	if  != nil {
		return nil, 
	}

	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 := .Call()
		return ()
	})
	return .Interface(), nil
}

func ( *asAnnotation) ( *annotated) (
	 []reflect.Type,
	 func([]reflect.Value) []reflect.Value,
	 error,
) {
	,  := .currentResultTypes()
	 := []reflect.StructField{_outAnnotationField}
	if  {
		 = [:len()-1]
	}
	,  := extractResultFields()

	for ,  := range  {
		 := .Type
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: ,
			Tag:  .Tag,
		}

		if  >= len(.types) || .types[].self {
			 = append(, )
			continue
		}

		if !.Implements(.types[].typ) {
			return nil, nil, fmt.Errorf("invalid fx.As: %v does not implement %v", , .types[])
		}
		.Type = .types[].typ
		 = append(, )
	}
	 := reflect.StructOf()

	var  []reflect.Type
	 = append(, )
	if  {
		 = append(, _typeOfError)
	}

	return , func( []reflect.Value) []reflect.Value {
		var (
			     error
			 []reflect.Value
		)

		for ,  := range  {
			if  == len()-1 &&  {
				// If hasError and this is the last item,
				// we are guaranteed that this is an error
				// object.
				if ,  := .Interface().(error);  != nil {
					 = 
				}
				continue
			}
			 = append(, )
		}

		 := reflect.New().Elem()
		for  := 1;  < .NumField(); ++ {
			.Field().Set((, ))
		}
		 = append(, )

		if  {
			if  != nil {
				 = append(, reflect.ValueOf())
			} else {
				 = append(, _nilError)
			}
		}

		return 
	}, nil
}

func extractResultFields( []reflect.Type) ([]reflect.StructField, func(int, []reflect.Value) reflect.Value) {
	var  []reflect.StructField
	if len() > 0 && isOut([0]) {
		for  := 1;  < [0].NumField(); ++ {
			 = append(, [0].Field())
		}
		return , func( int,  []reflect.Value) reflect.Value {
			return [0].Field()
		}
	}
	for ,  := range  {
		if isOut() {
			continue
		}
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: ,
		}
		 = append(, )
	}
	return , func( int,  []reflect.Value) reflect.Value {
		return [-1]
	}
}

type fromAnnotation struct {
	targets []interface{}
	types   []reflect.Type
}

var _ Annotation = (*fromAnnotation)(nil)

// From is an [Annotation] that annotates the parameter(s) for a function (i.e. a
// constructor) to be accepted from other provided types. It is analogous to the
// [As] for parameter types to the constructor.
//
// For example,
//
//	type Runner interface { Run() }
//	func NewFooRunner() *FooRunner // implements Runner
//	func NewRunnerWrap(r Runner) *RunnerWrap
//
//	fx.Provide(
//	  fx.Annotate(
//	    NewRunnerWrap,
//	    fx.From(new(*FooRunner)),
//	  ),
//	)
//
// Is equivalent to,
//
//	fx.Provide(func(r *FooRunner) *RunnerWrap {
//	  // need *FooRunner instead of Runner
//	  return NewRunnerWrap(r)
//	})
//
// When the annotated function takes in multiple parameters, each type gets
// mapped to corresponding positional parameter of the annotated function
//
// For example,
//
//	func NewBarRunner() *BarRunner // implements Runner
//	func NewRunnerWraps(r1 Runner, r2 Runner) *RunnerWraps
//
//	fx.Provide(
//	  fx.Annotate(
//	    NewRunnerWraps,
//	    fx.From(new(*FooRunner), new(*BarRunner)),
//	  ),
//	)
//
// Is equivalent to,
//
//	fx.Provide(func(r1 *FooRunner, r2 *BarRunner) *RunnerWraps {
//	  return NewRunnerWraps(r1, r2)
//	})
//
// From annotation cannot be used in a function that takes an [In] struct as a
// parameter.
func ( ...interface{}) Annotation {
	return &fromAnnotation{targets: }
}

func ( *fromAnnotation) ( *annotated) error {
	if len(.From) > 0 {
		return errors.New("cannot apply more than one line of From")
	}
	 := reflect.TypeOf(.Target)
	.types = make([]reflect.Type, len(.targets))
	for ,  := range .targets {
		if .IsVariadic() &&  == .NumIn()-1 {
			return errors.New("fx.From: cannot annotate a variadic argument")
		}
		 := reflect.TypeOf()
		if  == nil || .Kind() != reflect.Ptr {
			return fmt.Errorf("fx.From: argument must be a pointer to a type that implements some interface: got %v", )
		}
		.types[] = .Elem()
	}
	.From = .types
	return nil
}

// build builds and returns a constructor after applying a From annotation
func ( *fromAnnotation) ( *annotated) (interface{}, error) {
	, ,  := .parameters()
	if  != nil {
		return nil, 
	}
	,  := .currentResultTypes()

	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 = ()
		return .Call()
	})
	return .Interface(), nil
}

// parameters returns the type for the parameters of the annotated function,
// and a function that maps the arguments of the annotated function
// back to the arguments of the target function.
func ( *fromAnnotation) ( *annotated) (
	 []reflect.Type,
	 func([]reflect.Value) []reflect.Value,
	 error,
) {
	 := reflect.TypeOf(.Target)
	 = make([]reflect.Type, .NumIn())
	for  := 0;  < .NumIn(); ++ {
		[] = .In()
	}

	// No parameter annotations. Return the original types
	// and an identity function.
	if len(.targets) == 0 {
		return , func( []reflect.Value) []reflect.Value {
			return 
		}, nil
	}

	// Turn parameters into an fx.In struct.
	 := []reflect.StructField{_inAnnotationField}

	// The following situations may occur:
	// 1. there was a variadic argument, so it was pre-transformed.
	// 2. another parameter annotation was transformed (ex: ParamTags).
	// so need to visit fields of the fx.In struct.
	if len() > 0 && isIn([0]) {
		 := [0]

		for  := 1;  < .NumField(); ++ {
			 := .Field()
			 := reflect.StructField{
				Name: .Name,
				Type: .Type,
				Tag:  .Tag,
			}
			if -1 < len(.types) {
				 := .types[-1]
				if !.Implements(.Type) {
					return nil, nil, fmt.Errorf("invalid fx.From: %v does not implement %v", , .Type)
				}
				.Type = 
			}

			 = append(, )
		}

		 = []reflect.Type{reflect.StructOf()}
		return , func( []reflect.Value) []reflect.Value {
			 := [0]
			[0] = reflect.New().Elem()
			for  := 1;  < .NumField(); ++ {
				[0].Field().Set(.Field())
			}
			return 
		}, nil
	}

	for ,  := range  {
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: ,
		}
		if  < len(.types) {
			 := .types[]
			if !.Implements(.Type) {
				return nil, nil, fmt.Errorf("invalid fx.From: %v does not implement %v", , .Type)
			}
			.Type = 
		}

		 = append(, )
	}

	 = []reflect.Type{reflect.StructOf()}
	return , func( []reflect.Value) []reflect.Value {
		 := [0]
		 = [:0]
		for  := 0;  < .NumIn(); ++ {
			 = append(, .Field(+1))
		}
		return 
	}, nil
}

type annotated struct {
	Target      interface{}
	Annotations []Annotation
	ParamTags   []string
	ResultTags  []string
	As          [][]asType
	From        []reflect.Type
	FuncPtr     uintptr
	Hooks       []*lifecycleHookAnnotation
	// container is used to build private scopes for lifecycle hook functions
	// added via fx.OnStart and fx.OnStop annotations.
	container *dig.Container
}

func ( annotated) () string {
	var  strings.Builder
	.WriteString("fx.Annotate(")
	.WriteString(fxreflect.FuncName(.Target))
	if  := .ParamTags; len() > 0 {
		fmt.Fprintf(&, ", fx.ParamTags(%q)", )
	}
	if  := .ResultTags; len() > 0 {
		fmt.Fprintf(&, ", fx.ResultTags(%q)", )
	}
	if  := .As; len() > 0 {
		fmt.Fprintf(&, ", fx.As(%v)", )
	}
	if  := .From; len() > 0 {
		fmt.Fprintf(&, ", fx.From(%v)", )
	}
	return .String()
}

// Build builds and returns a constructor based on fx.In/fx.Out params and
// results wrapping the original constructor passed to fx.Annotate.
func ( *annotated) () (interface{}, error) {
	.container = dig.New()
	 := reflect.TypeOf(.Target)
	if .Kind() != reflect.Func {
		return nil, fmt.Errorf("must provide constructor function, got %v (%T)", .Target, .Target)
	}

	if  := .typeCheckOrigFn();  != nil {
		return nil, fmt.Errorf("invalid annotation function %T: %w", .Target, )
	}

	.applyOptionalTag()

	var (
		        error
		 []*lifecycleHookAnnotation
	)
	for ,  := range .Annotations {
		if ,  := .(*lifecycleHookAnnotation);  {
			 = append(, )
			continue
		}
		if .Target,  = .build();  != nil {
			return nil, 
		}
	}

	// need to call cleanUpAsResults before applying lifecycle annotations
	// to exclude the original results from the hook's scope if any
	// fx.As annotations were applied
	.cleanUpAsResults()

	for ,  := range  {
		if .Target,  = .build();  != nil {
			return nil, 
		}
	}
	return .Target, nil
}

// applyOptionalTag checks if function being annotated is variadic
// and applies optional tag to the variadic argument before
// applying any other annotations
func ( *annotated) () {
	 := reflect.TypeOf(.Target)
	if !.IsVariadic() {
		return
	}

	,  := .currentResultTypes()

	 := []reflect.StructField{_inAnnotationField}
	for  := 0;  < .NumIn(); ++ {
		 := reflect.StructField{
			Name: fmt.Sprintf("Field%d", ),
			Type: .In(),
		}
		if  == .NumIn()-1 {
			// Mark a variadic argument optional by default
			// so that just wrapping a function in fx.Annotate does not
			// suddenly introduce a required []arg dependency.
			.Tag = reflect.StructTag(`optional:"true"`)
		}
		 = append(, )
	}
	 := reflect.StructOf()
	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf([]reflect.Type{}, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
		 := [0]
		 = [:0]
		for  := 0;  < .NumIn(); ++ {
			 = append(, .Field(+1))
		}
		return .CallSlice()
	})
	.Target = .Interface()
}

// cleanUpAsResults does a check to see if an As annotation was applied.
// If there was any fx.As annotation applied, cleanUpAsResults wraps the
// function one more time to remove the results from the original function.
func ( *annotated) () {
	// clean up orig function results if there were any As annotations
	if len(.As) < 1 {
		return
	}
	 := .currentParamTypes()
	,  := .currentResultTypes()
	 := len(.As)
	if  {
		++
	}
	 := [len()-:]
	 := reflect.ValueOf(.Target)
	 := reflect.FuncOf(, , false)
	 := reflect.MakeFunc(, func( []reflect.Value) ( []reflect.Value) {
		 = .Call()
		 = [len()-:]
		return
	})
	.Target = .Interface()
}

// checks and returns a non-nil error if the target function:
// - returns an fx.Out struct as a result and has either a ResultTags or an As annotation
// - takes in an fx.In struct as a parameter and has either a ParamTags or a From annotation
// - has an error result not as the last result.
func ( *annotated) () error {
	 := reflect.TypeOf(.Target)
	 := .NumOut()
	for  := 0;  < ; ++ {
		 := .Out()
		if  == _typeOfError &&  != -1 {
			return fmt.Errorf(
				"only the last result can be an error: "+
					"%v (%v) returns error as result %d",
				fxreflect.FuncName(.Target), , )
		}
		if .Kind() != reflect.Struct {
			continue
		}
		if !dig.IsOut(reflect.New(.Out()).Elem().Interface()) {
			continue
		}
		if len(.ResultTags) > 0 || len(.As) > 0 {
			return errors.New("fx.Out structs cannot be annotated with fx.ResultTags or fx.As")
		}
	}
	for  := 0;  < .NumIn(); ++ {
		 := .In()
		if .Kind() != reflect.Struct {
			continue
		}
		if !dig.IsIn(reflect.New(.In()).Elem().Interface()) {
			continue
		}
		if len(.ParamTags) > 0 || len(.From) > 0 {
			return errors.New("fx.In structs cannot be annotated with fx.ParamTags or fx.From")
		}
	}
	return nil
}

func ( *annotated) () ( []reflect.Type,  bool) {
	 := reflect.TypeOf(.Target)
	 := .NumOut()
	 = make([]reflect.Type, )

	for  := 0;  < ; ++ {
		[] = .Out()
		if [] == _typeOfError &&  == -1 {
			 = true
		}
	}
	return , 
}

func ( *annotated) () []reflect.Type {
	 := reflect.TypeOf(.Target)
	 := make([]reflect.Type, .NumIn())

	for  := 0;  < .NumIn(); ++ {
		[] = .In()
	}
	return 
}

// Annotate lets you annotate a function's parameters and returns
// without you having to declare separate struct definitions for them.
//
// For example,
//
//	func NewGateway(ro, rw *db.Conn) *Gateway { ... }
//	fx.Provide(
//	  fx.Annotate(
//	    NewGateway,
//	    fx.ParamTags(`name:"ro" optional:"true"`, `name:"rw"`),
//	    fx.ResultTags(`name:"foo"`),
//	  ),
//	)
//
// Is equivalent to,
//
//	type params struct {
//	  fx.In
//
//	  RO *db.Conn `name:"ro" optional:"true"`
//	  RW *db.Conn `name:"rw"`
//	}
//
//	type result struct {
//	  fx.Out
//
//	  GW *Gateway `name:"foo"`
//	}
//
//	fx.Provide(func(p params) result {
//	   return result{GW: NewGateway(p.RO, p.RW)}
//	})
//
// Using the same annotation multiple times is invalid.
// For example, the following will fail with an error:
//
//	fx.Provide(
//	  fx.Annotate(
//	    NewGateWay,
//	    fx.ParamTags(`name:"ro" optional:"true"`),
//	    fx.ParamTags(`name:"rw"), // ERROR: ParamTags was already used above
//	    fx.ResultTags(`name:"foo"`)
//	  )
//	)
//
// If more tags are given than the number of parameters/results, only
// the ones up to the number of parameters/results will be applied.
//
// # Variadic functions
//
// If the provided function is variadic, Annotate treats its parameter as a
// slice. For example,
//
//	fx.Annotate(func(w io.Writer, rs ...io.Reader) {
//	  // ...
//	}, ...)
//
// Is equivalent to,
//
//	fx.Annotate(func(w io.Writer, rs []io.Reader) {
//	  // ...
//	}, ...)
//
// You can use variadic parameters with Fx's value groups.
// For example,
//
//	fx.Annotate(func(mux *http.ServeMux, handlers ...http.Handler) {
//	  // ...
//	}, fx.ParamTags(``, `group:"server"`))
//
// If we provide the above to the application,
// any constructor in the Fx application can inject its HTTP handlers
// by using [Annotate], [Annotated], or [Out].
//
//	fx.Annotate(
//	  func(..) http.Handler { ... },
//	  fx.ResultTags(`group:"server"`),
//	)
//
//	fx.Annotated{
//	  Target: func(..) http.Handler { ... },
//	  Group:  "server",
//	}
func ( interface{},  ...Annotation) interface{} {
	 := annotated{Target: }
	for ,  := range  {
		if  := .apply(&);  != nil {
			return annotationError{
				target: ,
				err:    ,
			}
		}
	}
	.Annotations = 
	return 
}