1 // Copyright 2012 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 declares the data types and implements 6 // the algorithms for type-checking of Go packages. Use 7 // Config.Check to invoke the type checker for a package. 8 // Alternatively, create a new type checker with NewChecker 9 // and invoke it incrementally by calling Checker.Files. 10 // 11 // Type-checking consists of several interdependent phases: 12 // 13 // Name resolution maps each identifier (ast.Ident) in the program to the 14 // language object (Object) it denotes. 15 // Use Info.{Defs,Uses,Implicits} for the results of name resolution. 16 // 17 // Constant folding computes the exact constant value (constant.Value) 18 // for every expression (ast.Expr) that is a compile-time constant. 19 // Use Info.Types[expr].Value for the results of constant folding. 20 // 21 // Type inference computes the type (Type) of every expression (ast.Expr) 22 // and checks for compliance with the language specification. 23 // Use Info.Types[expr].Type for the results of type inference. 24 // 25 // For a tutorial, see https://golang.org/s/types-tutorial. 26 // 27 package types 28 29 import ( 30 "bytes" 31 "fmt" 32 "go/ast" 33 "go/constant" 34 "go/token" 35 ) 36 37 // An Error describes a type-checking error; it implements the error interface. 38 // A "soft" error is an error that still permits a valid interpretation of a 39 // package (such as "unused variable"); "hard" errors may lead to unpredictable 40 // behavior if ignored. 41 type Error struct { 42 Fset *token.FileSet // file set for interpretation of Pos 43 Pos token.Pos // error position 44 Msg string // error message 45 Soft bool // if set, error is "soft" 46 47 // go116code is a future API, unexported as the set of error codes is large 48 // and likely to change significantly during experimentation. Tools wishing 49 // to preview this feature may read go116code using reflection (see 50 // errorcodes_test.go), but beware that there is no guarantee of future 51 // compatibility. 52 go116code errorCode 53 go116start token.Pos 54 go116end token.Pos 55 } 56 57 // Error returns an error string formatted as follows: 58 // filename:line:column: message 59 func (err Error) Error() string { 60 return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg) 61 } 62 63 // An Importer resolves import paths to Packages. 64 // 65 // CAUTION: This interface does not support the import of locally 66 // vendored packages. See https://golang.org/s/go15vendor. 67 // If possible, external implementations should implement ImporterFrom. 68 type Importer interface { 69 // Import returns the imported package for the given import path. 70 // The semantics is like for ImporterFrom.ImportFrom except that 71 // dir and mode are ignored (since they are not present). 72 Import(path string) (*Package, error) 73 } 74 75 // ImportMode is reserved for future use. 76 type ImportMode int 77 78 // An ImporterFrom resolves import paths to packages; it 79 // supports vendoring per https://golang.org/s/go15vendor. 80 // Use go/importer to obtain an ImporterFrom implementation. 81 type ImporterFrom interface { 82 // Importer is present for backward-compatibility. Calling 83 // Import(path) is the same as calling ImportFrom(path, "", 0); 84 // i.e., locally vendored packages may not be found. 85 // The types package does not call Import if an ImporterFrom 86 // is present. 87 Importer 88 89 // ImportFrom returns the imported package for the given import 90 // path when imported by a package file located in dir. 91 // If the import failed, besides returning an error, ImportFrom 92 // is encouraged to cache and return a package anyway, if one 93 // was created. This will reduce package inconsistencies and 94 // follow-on type checker errors due to the missing package. 95 // The mode value must be 0; it is reserved for future use. 96 // Two calls to ImportFrom with the same path and dir must 97 // return the same package. 98 ImportFrom(path, dir string, mode ImportMode) (*Package, error) 99 } 100 101 // A Config specifies the configuration for type checking. 102 // The zero value for Config is a ready-to-use default configuration. 103 type Config struct { 104 // goVersion describes the accepted Go language version. The string 105 // must follow the format "go%d.%d" (e.g. "go1.12") or it must be 106 // empty; an empty string indicates the latest language version. 107 // If the format is invalid, invoking the type checker will cause a 108 // panic. 109 goVersion string 110 111 // If IgnoreFuncBodies is set, function bodies are not 112 // type-checked. 113 IgnoreFuncBodies bool 114 115 // If FakeImportC is set, `import "C"` (for packages requiring Cgo) 116 // declares an empty "C" package and errors are omitted for qualified 117 // identifiers referring to package C (which won't find an object). 118 // This feature is intended for the standard library cmd/api tool. 119 // 120 // Caution: Effects may be unpredictable due to follow-on errors. 121 // Do not use casually! 122 FakeImportC bool 123 124 // If go115UsesCgo is set, the type checker expects the 125 // _cgo_gotypes.go file generated by running cmd/cgo to be 126 // provided as a package source file. Qualified identifiers 127 // referring to package C will be resolved to cgo-provided 128 // declarations within _cgo_gotypes.go. 129 // 130 // It is an error to set both FakeImportC and go115UsesCgo. 131 go115UsesCgo bool 132 133 // If Error != nil, it is called with each error found 134 // during type checking; err has dynamic type Error. 135 // Secondary errors (for instance, to enumerate all types 136 // involved in an invalid recursive type declaration) have 137 // error strings that start with a '\t' character. 138 // If Error == nil, type-checking stops with the first 139 // error found. 140 Error func(err error) 141 142 // An importer is used to import packages referred to from 143 // import declarations. 144 // If the installed importer implements ImporterFrom, the type 145 // checker calls ImportFrom instead of Import. 146 // The type checker reports an error if an importer is needed 147 // but none was installed. 148 Importer Importer 149 150 // If Sizes != nil, it provides the sizing functions for package unsafe. 151 // Otherwise SizesFor("gc", "amd64") is used instead. 152 Sizes Sizes 153 154 // If DisableUnusedImportCheck is set, packages are not checked 155 // for unused imports. 156 DisableUnusedImportCheck bool 157 } 158 159 func srcimporter_setUsesCgo(conf *Config) { 160 conf.go115UsesCgo = true 161 } 162 163 // The Info struct is found in api_notypeparams.go and api_typeparams.go. 164 165 // TypeOf returns the type of expression e, or nil if not found. 166 // Precondition: the Types, Uses and Defs maps are populated. 167 // 168 func (info *Info) TypeOf(e ast.Expr) Type { 169 if t, ok := info.Types[e]; ok { 170 return t.Type 171 } 172 if id, _ := e.(*ast.Ident); id != nil { 173 if obj := info.ObjectOf(id); obj != nil { 174 return obj.Type() 175 } 176 } 177 return nil 178 } 179 180 // ObjectOf returns the object denoted by the specified id, 181 // or nil if not found. 182 // 183 // If id is an embedded struct field, ObjectOf returns the field (*Var) 184 // it defines, not the type (*TypeName) it uses. 185 // 186 // Precondition: the Uses and Defs maps are populated. 187 // 188 func (info *Info) ObjectOf(id *ast.Ident) Object { 189 if obj := info.Defs[id]; obj != nil { 190 return obj 191 } 192 return info.Uses[id] 193 } 194 195 // TypeAndValue reports the type and value (for constants) 196 // of the corresponding expression. 197 type TypeAndValue struct { 198 mode operandMode 199 Type Type 200 Value constant.Value 201 } 202 203 // IsVoid reports whether the corresponding expression 204 // is a function call without results. 205 func (tv TypeAndValue) IsVoid() bool { 206 return tv.mode == novalue 207 } 208 209 // IsType reports whether the corresponding expression specifies a type. 210 func (tv TypeAndValue) IsType() bool { 211 return tv.mode == typexpr 212 } 213 214 // IsBuiltin reports whether the corresponding expression denotes 215 // a (possibly parenthesized) built-in function. 216 func (tv TypeAndValue) IsBuiltin() bool { 217 return tv.mode == builtin 218 } 219 220 // IsValue reports whether the corresponding expression is a value. 221 // Builtins are not considered values. Constant values have a non- 222 // nil Value. 223 func (tv TypeAndValue) IsValue() bool { 224 switch tv.mode { 225 case constant_, variable, mapindex, value, commaok, commaerr: 226 return true 227 } 228 return false 229 } 230 231 // IsNil reports whether the corresponding expression denotes the 232 // predeclared value nil. 233 func (tv TypeAndValue) IsNil() bool { 234 return tv.mode == value && tv.Type == Typ[UntypedNil] 235 } 236 237 // Addressable reports whether the corresponding expression 238 // is addressable (https://golang.org/ref/spec#Address_operators). 239 func (tv TypeAndValue) Addressable() bool { 240 return tv.mode == variable 241 } 242 243 // Assignable reports whether the corresponding expression 244 // is assignable to (provided a value of the right type). 245 func (tv TypeAndValue) Assignable() bool { 246 return tv.mode == variable || tv.mode == mapindex 247 } 248 249 // HasOk reports whether the corresponding expression may be 250 // used on the rhs of a comma-ok assignment. 251 func (tv TypeAndValue) HasOk() bool { 252 return tv.mode == commaok || tv.mode == mapindex 253 } 254 255 // _Inferred reports the _Inferred type arguments and signature 256 // for a parameterized function call that uses type inference. 257 type _Inferred struct { 258 Targs []Type 259 Sig *Signature 260 } 261 262 // An Initializer describes a package-level variable, or a list of variables in case 263 // of a multi-valued initialization expression, and the corresponding initialization 264 // expression. 265 type Initializer struct { 266 Lhs []*Var // var Lhs = Rhs 267 Rhs ast.Expr 268 } 269 270 func (init *Initializer) String() string { 271 var buf bytes.Buffer 272 for i, lhs := range init.Lhs { 273 if i > 0 { 274 buf.WriteString(", ") 275 } 276 buf.WriteString(lhs.Name()) 277 } 278 buf.WriteString(" = ") 279 WriteExpr(&buf, init.Rhs) 280 return buf.String() 281 } 282 283 // Check type-checks a package and returns the resulting package object and 284 // the first error if any. Additionally, if info != nil, Check populates each 285 // of the non-nil maps in the Info struct. 286 // 287 // The package is marked as complete if no errors occurred, otherwise it is 288 // incomplete. See Config.Error for controlling behavior in the presence of 289 // errors. 290 // 291 // The package is specified by a list of *ast.Files and corresponding 292 // file set, and the package path the package is identified with. 293 // The clean path must not be empty or dot ("."). 294 func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) { 295 pkg := NewPackage(path, "") 296 return pkg, NewChecker(conf, fset, pkg, info).Files(files) 297 } 298 299 // AssertableTo reports whether a value of type V can be asserted to have type T. 300 func AssertableTo(V *Interface, T Type) bool { 301 m, _ := (*Checker)(nil).assertableTo(V, T) 302 return m == nil 303 } 304 305 // AssignableTo reports whether a value of type V is assignable to a variable of type T. 306 func AssignableTo(V, T Type) bool { 307 x := operand{mode: value, typ: V} 308 ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x 309 return ok 310 } 311 312 // ConvertibleTo reports whether a value of type V is convertible to a value of type T. 313 func ConvertibleTo(V, T Type) bool { 314 x := operand{mode: value, typ: V} 315 return x.convertibleTo(nil, T, nil) // check not needed for non-constant x 316 } 317 318 // Implements reports whether type V implements interface T. 319 func Implements(V Type, T *Interface) bool { 320 f, _ := MissingMethod(V, T, true) 321 return f == nil 322 } 323 324 // Identical reports whether x and y are identical types. 325 // Receivers of Signature types are ignored. 326 func Identical(x, y Type) bool { 327 return (*Checker)(nil).identical(x, y) 328 } 329 330 // IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored. 331 // Receivers of Signature types are ignored. 332 func IdenticalIgnoreTags(x, y Type) bool { 333 return (*Checker)(nil).identicalIgnoreTags(x, y) 334 } 335