...

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