Example #1
0
func assignable(t, u types.Type) bool {
	if t == nil || u == nil {
		return false
	}
	if t, ok := t.(*types.Basic); ok && t.Info&types.IsUntyped != 0 {
		// TODO: consider representability of const values
		switch u := underlying(u).(type) {
		case *types.Interface:
			return u.Empty()
		case *types.Basic:
			int := t.Info&types.IsInteger != 0
			float := t.Info&types.IsFloat != 0
			complex := t.Info&types.IsComplex != 0
			switch {
			case u.Info&types.IsBoolean != 0:
				return t.Info&types.IsBoolean != 0
			case u.Info&types.IsInteger != 0:
				return int
			case u.Info&types.IsFloat != 0:
				return int || float
			case u.Info&types.IsComplex != 0:
				return int || float || complex
			case u.Info&types.IsString != 0:
				return t.Info&types.IsString != 0
			}
		}
		return false
	}
	return types.IsAssignableTo(t, u)
}
Example #2
0
// TODO: use the version from ssa or go/types
func intuitiveMethodSet(T types.Type) []*types.Selection {
	var result []*types.Selection
	mset := types.NewMethodSet(T)
	if _, ok := T.Underlying().(*types.Interface); ok {
		for i, n := 0, mset.Len(); i < n; i++ {
			result = append(result, mset.At(i))
		}
	} else {
		pmset := types.NewMethodSet(types.NewPointer(T))
		for i, n := 0, pmset.Len(); i < n; i++ {
			meth := pmset.At(i)
			if m := mset.Lookup(meth.Obj.GetPkg(), meth.Obj.GetName()); m != nil {
				meth = m
			}
			result = append(result, meth)
		}
	}
	return result
}
Example #3
0
// hashFor computes the hash of t.
func (h Hasher) hashFor(t types.Type) uint32 {
	// See IsIdentical for rationale.
	switch t := t.(type) {
	case *types.Basic:
		return uint32(t.Kind)

	case *types.Array:
		return 9043 + 2*uint32(t.Len) + 3*h.Hash(t.Elem)

	case *types.Slice:
		return 9049 + 2*h.Hash(t.Elem)

	case *types.Struct:
		var hash uint32 = 9059
		for i, n := 0, t.NumFields(); i < n; i++ {
			f := t.Field(i)
			if f.Anonymous() {
				hash += 8861
			}
			hash += hashString(t.Tag(i))
			hash += hashString(f.GetName()) // (ignore f.Pkg)
			hash += h.Hash(f.GetType())
		}
		return hash

	case *types.Pointer:
		return 9067 + 2*h.Hash(t.Elem)

	case *types.Signature:
		var hash uint32 = 9091
		if t.IsVariadic() {
			hash *= 8863
		}
		return hash + 3*h.hashTuple(t.Params) + 5*h.hashTuple(t.Results)

	case *types.Interface:
		var hash uint32 = 9103
		for i, n := 0, t.NumMethods(); i < n; i++ {
			// See go/types.identicalMethods for rationale.
			// Method order is not significant.
			// Ignore m.GetPkg().
			m := t.Method(i)
			hash += 3*hashString(m.GetName()) + 5*h.Hash(m.GetType())
		}
		return hash

	case *types.Map:
		return 9109 + 2*h.Hash(t.Key) + 3*h.Hash(t.Elem)

	case *types.Chan:
		return 9127 + 2*uint32(t.Dir) + 3*h.Hash(t.Elem)

	case *types.Named:
		// Not safe with a copying GC; objects may move.
		return uint32(uintptr(unsafe.Pointer(t.Obj)))

	case *types.Tuple:
		return h.hashTuple(t)
	}
	panic(t)
}