func (check *Checker) assignment(mapping map[*TypeParam]Type, x *operand, T Type, context string) {
	check.singleValue(x)
	switch x.mode {
	case invalid:
		return  
	case constant_, variable, mapindex, value, commaok:
	default:
		unreachable()
	}
	if typeParam, ok := T.Underlying().(*TypeParam); ok && mapping != nil {
		if typ, ok := mapping[typeParam]; ok {
			T = typ
		} else {
			if isUntyped(x.typ) {
				x.typ = Default(x.typ)
			}
			if !assignableToTypeParam(x.typ, typeParam) {
				check.errorf(x.pos(), "value of type %v does not satisfy the restrictions of %v", x.typ, typeParam)
				x.mode = invalid
				return
			}
			mapping[typeParam] = x.typ
			return
		}
	}
	if isUntyped(x.typ) {
		target := T
		if T == nil || IsInterface(T) {
			if T == nil && x.typ == Typ[UntypedNil] {
				check.errorf(x.pos(), "use of untyped nil in %s", context)
				x.mode = invalid
				return
			}
			target = Default(x.typ)
		}
		check.convertUntyped(x, target)
		if x.mode == invalid {
			return
		}
	}
	if sig, ok := x.typ.(*Signature); ok && len(sig.typeParams) > 0 {
		check.errorf(x.pos(), "generic function used as value in %s", context)
		return
	}
	if T == nil {
		return
	}
	if reason := ""; !x.assignableTo(mapping, check.conf, T, &reason) {
		if reason != "" {
			check.errorf(x.pos(), "cannot use %s as %s value in %s: %s", x, mapType(mapping, T, make(map[Type]Type)), context, reason)
		} else {
			check.errorf(x.pos(), "cannot use %s as %s value in %s", x, mapType(mapping, T, make(map[Type]Type)), context)
		}
		x.mode = invalid
	}
}
assignment reports whether x can be assigned to a variable of type T,
if necessary by attempting to convert untyped values to the appropriate
type. context describes the context in which the assignment takes place.
Use T == nil to indicate assignment to an untyped blank identifier.
x.mode is set to invalid if the assignment failed.
package types
import (
	"github.com/faiface/generics/go/ast"
	"github.com/faiface/generics/go/token"
)
func assignableToTypeParam(x Type, p *TypeParam) bool {
	if p.Restriction()&RestrictionEq != 0 && !Comparable(x) {
		return false
	}
	if p.Restriction()&RestrictionOrd != 0 && !isOrdered(x) {
		return false
	}
	if p.Restriction()&RestrictionNum != 0 && !isNumeric(x) {
		return false
	}
	return true
}