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

Documentation: cmd/compile/internal/types

     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