Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/types/sanitize.go

Documentation: go/types

     1  // Copyright 2020 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  // sanitizeInfo walks the types contained in info to ensure that all instances
     8  // are expanded.
     9  //
    10  // This includes some objects that may be shared across concurrent
    11  // type-checking passes (such as those in the universe scope), so we are
    12  // careful here not to write types that are already sanitized. This avoids a
    13  // data race as any shared types should already be sanitized.
    14  func sanitizeInfo(info *Info) {
    15  	var s sanitizer = make(map[Type]Type)
    16  
    17  	// Note: Some map entries are not references.
    18  	// If modified, they must be assigned back.
    19  
    20  	for e, tv := range info.Types {
    21  		if typ := s.typ(tv.Type); typ != tv.Type {
    22  			tv.Type = typ
    23  			info.Types[e] = tv
    24  		}
    25  	}
    26  
    27  	inferred := getInferred(info)
    28  	for e, inf := range inferred {
    29  		changed := false
    30  		for i, targ := range inf.Targs {
    31  			if typ := s.typ(targ); typ != targ {
    32  				inf.Targs[i] = typ
    33  				changed = true
    34  			}
    35  		}
    36  		if typ := s.typ(inf.Sig); typ != inf.Sig {
    37  			inf.Sig = typ.(*Signature)
    38  			changed = true
    39  		}
    40  		if changed {
    41  			inferred[e] = inf
    42  		}
    43  	}
    44  
    45  	for _, obj := range info.Defs {
    46  		if obj != nil {
    47  			if typ := s.typ(obj.Type()); typ != obj.Type() {
    48  				obj.setType(typ)
    49  			}
    50  		}
    51  	}
    52  
    53  	for _, obj := range info.Uses {
    54  		if obj != nil {
    55  			if typ := s.typ(obj.Type()); typ != obj.Type() {
    56  				obj.setType(typ)
    57  			}
    58  		}
    59  	}
    60  
    61  	// TODO(gri) sanitize as needed
    62  	// - info.Implicits
    63  	// - info.Selections
    64  	// - info.Scopes
    65  	// - info.InitOrder
    66  }
    67  
    68  type sanitizer map[Type]Type
    69  
    70  func (s sanitizer) typ(typ Type) Type {
    71  	if typ == nil {
    72  		return nil
    73  	}
    74  
    75  	if t, found := s[typ]; found {
    76  		return t
    77  	}
    78  	s[typ] = typ
    79  
    80  	switch t := typ.(type) {
    81  	case *Basic, *bottom, *top:
    82  		// nothing to do
    83  
    84  	case *Array:
    85  		if elem := s.typ(t.elem); elem != t.elem {
    86  			t.elem = elem
    87  		}
    88  
    89  	case *Slice:
    90  		if elem := s.typ(t.elem); elem != t.elem {
    91  			t.elem = elem
    92  		}
    93  
    94  	case *Struct:
    95  		s.varList(t.fields)
    96  
    97  	case *Pointer:
    98  		if base := s.typ(t.base); base != t.base {
    99  			t.base = base
   100  		}
   101  
   102  	case *Tuple:
   103  		s.tuple(t)
   104  
   105  	case *Signature:
   106  		s.var_(t.recv)
   107  		s.tuple(t.params)
   108  		s.tuple(t.results)
   109  
   110  	case *_Sum:
   111  		s.typeList(t.types)
   112  
   113  	case *Interface:
   114  		s.funcList(t.methods)
   115  		if types := s.typ(t.types); types != t.types {
   116  			t.types = types
   117  		}
   118  		s.typeList(t.embeddeds)
   119  		s.funcList(t.allMethods)
   120  		if allTypes := s.typ(t.allTypes); allTypes != t.allTypes {
   121  			t.allTypes = allTypes
   122  		}
   123  
   124  	case *Map:
   125  		if key := s.typ(t.key); key != t.key {
   126  			t.key = key
   127  		}
   128  		if elem := s.typ(t.elem); elem != t.elem {
   129  			t.elem = elem
   130  		}
   131  
   132  	case *Chan:
   133  		if elem := s.typ(t.elem); elem != t.elem {
   134  			t.elem = elem
   135  		}
   136  
   137  	case *Named:
   138  		if debug && t.check != nil {
   139  			panic("internal error: Named.check != nil")
   140  		}
   141  		if orig := s.typ(t.orig); orig != t.orig {
   142  			t.orig = orig
   143  		}
   144  		if under := s.typ(t.underlying); under != t.underlying {
   145  			t.underlying = under
   146  		}
   147  		s.typeList(t.targs)
   148  		s.funcList(t.methods)
   149  
   150  	case *_TypeParam:
   151  		if bound := s.typ(t.bound); bound != t.bound {
   152  			t.bound = bound
   153  		}
   154  
   155  	case *instance:
   156  		typ = t.expand()
   157  		s[t] = typ
   158  
   159  	default:
   160  		panic("unimplemented")
   161  	}
   162  
   163  	return typ
   164  }
   165  
   166  func (s sanitizer) var_(v *Var) {
   167  	if v != nil {
   168  		if typ := s.typ(v.typ); typ != v.typ {
   169  			v.typ = typ
   170  		}
   171  	}
   172  }
   173  
   174  func (s sanitizer) varList(list []*Var) {
   175  	for _, v := range list {
   176  		s.var_(v)
   177  	}
   178  }
   179  
   180  func (s sanitizer) tuple(t *Tuple) {
   181  	if t != nil {
   182  		s.varList(t.vars)
   183  	}
   184  }
   185  
   186  func (s sanitizer) func_(f *Func) {
   187  	if f != nil {
   188  		if typ := s.typ(f.typ); typ != f.typ {
   189  			f.typ = typ
   190  		}
   191  	}
   192  }
   193  
   194  func (s sanitizer) funcList(list []*Func) {
   195  	for _, f := range list {
   196  		s.func_(f)
   197  	}
   198  }
   199  
   200  func (s sanitizer) typeList(list []Type) {
   201  	for i, t := range list {
   202  		if typ := s.typ(t); typ != t {
   203  			list[i] = typ
   204  		}
   205  	}
   206  }
   207  

View as plain text