...

Source file src/pkg/cmd/compile/internal/types/identity.go

     1	// Copyright 2018 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package types
     6	
     7	// Identical reports whether t1 and t2 are identical types, following
     8	// the spec rules. Receiver parameter types are ignored.
     9	func Identical(t1, t2 *Type) bool {
    10		return identical(t1, t2, true, nil)
    11	}
    12	
    13	// IdenticalIgnoreTags is like Identical, but it ignores struct tags
    14	// for struct identity.
    15	func IdenticalIgnoreTags(t1, t2 *Type) bool {
    16		return identical(t1, t2, false, nil)
    17	}
    18	
    19	type typePair struct {
    20		t1 *Type
    21		t2 *Type
    22	}
    23	
    24	func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) bool {
    25		if t1 == t2 {
    26			return true
    27		}
    28		if t1 == nil || t2 == nil || t1.Etype != t2.Etype || t1.Broke() || t2.Broke() {
    29			return false
    30		}
    31		if t1.Sym != nil || t2.Sym != nil {
    32			// Special case: we keep byte/uint8 and rune/int32
    33			// separate for error messages. Treat them as equal.
    34			switch t1.Etype {
    35			case TUINT8:
    36				return (t1 == Types[TUINT8] || t1 == Bytetype) && (t2 == Types[TUINT8] || t2 == Bytetype)
    37			case TINT32:
    38				return (t1 == Types[TINT32] || t1 == Runetype) && (t2 == Types[TINT32] || t2 == Runetype)
    39			default:
    40				return false
    41			}
    42		}
    43	
    44		// Any cyclic type must go through a named type, and if one is
    45		// named, it is only identical to the other if they are the
    46		// same pointer (t1 == t2), so there's no chance of chasing
    47		// cycles ad infinitum, so no need for a depth counter.
    48		if assumedEqual == nil {
    49			assumedEqual = make(map[typePair]struct{})
    50		} else if _, ok := assumedEqual[typePair{t1, t2}]; ok {
    51			return true
    52		}
    53		assumedEqual[typePair{t1, t2}] = struct{}{}
    54	
    55		switch t1.Etype {
    56		case TINTER:
    57			if t1.NumFields() != t2.NumFields() {
    58				return false
    59			}
    60			for i, f1 := range t1.FieldSlice() {
    61				f2 := t2.Field(i)
    62				if f1.Sym != f2.Sym || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
    63					return false
    64				}
    65			}
    66			return true
    67	
    68		case TSTRUCT:
    69			if t1.NumFields() != t2.NumFields() {
    70				return false
    71			}
    72			for i, f1 := range t1.FieldSlice() {
    73				f2 := t2.Field(i)
    74				if f1.Sym != f2.Sym || f1.Embedded != f2.Embedded || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
    75					return false
    76				}
    77				if cmpTags && f1.Note != f2.Note {
    78					return false
    79				}
    80			}
    81			return true
    82	
    83		case TFUNC:
    84			// Check parameters and result parameters for type equality.
    85			// We intentionally ignore receiver parameters for type
    86			// equality, because they're never relevant.
    87			for _, f := range ParamsResults {
    88				// Loop over fields in structs, ignoring argument names.
    89				fs1, fs2 := f(t1).FieldSlice(), f(t2).FieldSlice()
    90				if len(fs1) != len(fs2) {
    91					return false
    92				}
    93				for i, f1 := range fs1 {
    94					f2 := fs2[i]
    95					if f1.IsDDD() != f2.IsDDD() || !identical(f1.Type, f2.Type, cmpTags, assumedEqual) {
    96						return false
    97					}
    98				}
    99			}
   100			return true
   101	
   102		case TARRAY:
   103			if t1.NumElem() != t2.NumElem() {
   104				return false
   105			}
   106	
   107		case TCHAN:
   108			if t1.ChanDir() != t2.ChanDir() {
   109				return false
   110			}
   111	
   112		case TMAP:
   113			if !identical(t1.Key(), t2.Key(), cmpTags, assumedEqual) {
   114				return false
   115			}
   116		}
   117	
   118		return identical(t1.Elem(), t2.Elem(), cmpTags, assumedEqual)
   119	}
   120	

View as plain text