github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/types2/api.go (about) 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 (syntax.Name) 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 (syntax.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 (syntax.Expr) 22 // and checks for compliance with the language specification. 23 // Use Info.Types[expr].Type for the results of type inference. 24 package types2 25 26 import ( 27 "fmt" 28 "go/constant" 29 "strings" 30 31 "github.com/go-asm/go/cmd/compile/syntax" 32 . "github.com/go-asm/go/types/errors" 33 ) 34 35 // An Error describes a type-checking error; it implements the error interface. 36 // A "soft" error is an error that still permits a valid interpretation of a 37 // package (such as "unused variable"); "hard" errors may lead to unpredictable 38 // behavior if ignored. 39 type Error struct { 40 Pos syntax.Pos // error position 41 Msg string // default error message, user-friendly 42 Full string // full error message, for debugging (may contain internal details) 43 Soft bool // if set, error is "soft" 44 Code Code // error code 45 } 46 47 // Error returns an error string formatted as follows: 48 // filename:line:column: message 49 func (err Error) Error() string { 50 return fmt.Sprintf("%s: %s", err.Pos, err.Msg) 51 } 52 53 // FullError returns an error string like Error, buy it may contain 54 // type-checker internal details such as subscript indices for type 55 // parameters and more. Useful for debugging. 56 func (err Error) FullError() string { 57 return fmt.Sprintf("%s: %s", err.Pos, err.Full) 58 } 59 60 // An ArgumentError holds an error associated with an argument index. 61 type ArgumentError struct { 62 Index int 63 Err error 64 } 65 66 func (e *ArgumentError) Error() string { return e.Err.Error() } 67 func (e *ArgumentError) Unwrap() error { return e.Err } 68 69 // An Importer resolves import paths to Packages. 70 // 71 // CAUTION: This interface does not support the import of locally 72 // vendored packages. See https://golang.org/s/go15vendor. 73 // If possible, external implementations should implement ImporterFrom. 74 type Importer interface { 75 // Import returns the imported package for the given import path. 76 // The semantics is like for ImporterFrom.ImportFrom except that 77 // dir and mode are ignored (since they are not present). 78 Import(path string) (*Package, error) 79 } 80 81 // ImportMode is reserved for future use. 82 type ImportMode int 83 84 // An ImporterFrom resolves import paths to packages; it 85 // supports vendoring per https://golang.org/s/go15vendor. 86 // Use go/importer to obtain an ImporterFrom implementation. 87 type ImporterFrom interface { 88 // Importer is present for backward-compatibility. Calling 89 // Import(path) is the same as calling ImportFrom(path, "", 0); 90 // i.e., locally vendored packages may not be found. 91 // The types package does not call Import if an ImporterFrom 92 // is present. 93 Importer 94 95 // ImportFrom returns the imported package for the given import 96 // path when imported by a package file located in dir. 97 // If the import failed, besides returning an error, ImportFrom 98 // is encouraged to cache and return a package anyway, if one 99 // was created. This will reduce package inconsistencies and 100 // follow-on type checker errors due to the missing package. 101 // The mode value must be 0; it is reserved for future use. 102 // Two calls to ImportFrom with the same path and dir must 103 // return the same package. 104 ImportFrom(path, dir string, mode ImportMode) (*Package, error) 105 } 106 107 // A Config specifies the configuration for type checking. 108 // The zero value for Config is a ready-to-use default configuration. 109 type Config struct { 110 // Context is the context used for resolving global identifiers. If nil, the 111 // type checker will initialize this field with a newly created context. 112 Context *Context 113 114 // GoVersion describes the accepted Go language version. The string must 115 // start with a prefix of the form "go%d.%d" (e.g. "go1.20", "go1.21rc1", or 116 // "go1.21.0") or it must be empty; an empty string disables Go language 117 // version checks. If the format is invalid, invoking the type checker will 118 // result in an error. 119 GoVersion string 120 121 // If IgnoreFuncBodies is set, function bodies are not 122 // type-checked. 123 IgnoreFuncBodies bool 124 125 // If FakeImportC is set, `import "C"` (for packages requiring Cgo) 126 // declares an empty "C" package and errors are omitted for qualified 127 // identifiers referring to package C (which won't find an object). 128 // This feature is intended for the standard library cmd/api tool. 129 // 130 // Caution: Effects may be unpredictable due to follow-on errors. 131 // Do not use casually! 132 FakeImportC bool 133 134 // If IgnoreBranchErrors is set, branch/label errors are ignored. 135 IgnoreBranchErrors bool 136 137 // If go115UsesCgo is set, the type checker expects the 138 // _cgo_gotypes.go file generated by running cmd/cgo to be 139 // provided as a package source file. Qualified identifiers 140 // referring to package C will be resolved to cgo-provided 141 // declarations within _cgo_gotypes.go. 142 // 143 // It is an error to set both FakeImportC and go115UsesCgo. 144 go115UsesCgo bool 145 146 // If Trace is set, a debug trace is printed to stdout. 147 Trace bool 148 149 // If Error != nil, it is called with each error found 150 // during type checking; err has dynamic type Error. 151 // Secondary errors (for instance, to enumerate all types 152 // involved in an invalid recursive type declaration) have 153 // error strings that start with a '\t' character. 154 // If Error == nil, type-checking stops with the first 155 // error found. 156 Error func(err error) 157 158 // An importer is used to import packages referred to from 159 // import declarations. 160 // If the installed importer implements ImporterFrom, the type 161 // checker calls ImportFrom instead of Import. 162 // The type checker reports an error if an importer is needed 163 // but none was installed. 164 Importer Importer 165 166 // If Sizes != nil, it provides the sizing functions for package unsafe. 167 // Otherwise SizesFor("gc", "amd64") is used instead. 168 Sizes Sizes 169 170 // If DisableUnusedImportCheck is set, packages are not checked 171 // for unused imports. 172 DisableUnusedImportCheck bool 173 174 // If a non-empty ErrorURL format string is provided, it is used 175 // to format an error URL link that is appended to the first line 176 // of an error message. ErrorURL must be a format string containing 177 // exactly one "%s" format, e.g. "[go.dev/e/%s]". 178 ErrorURL string 179 } 180 181 func srcimporter_setUsesCgo(conf *Config) { 182 conf.go115UsesCgo = true 183 } 184 185 // Info holds result type information for a type-checked package. 186 // Only the information for which a map is provided is collected. 187 // If the package has type errors, the collected information may 188 // be incomplete. 189 type Info struct { 190 // Types maps expressions to their types, and for constant 191 // expressions, also their values. Invalid expressions are 192 // omitted. 193 // 194 // For (possibly parenthesized) identifiers denoting built-in 195 // functions, the recorded signatures are call-site specific: 196 // if the call result is not a constant, the recorded type is 197 // an argument-specific signature. Otherwise, the recorded type 198 // is invalid. 199 // 200 // The Types map does not record the type of every identifier, 201 // only those that appear where an arbitrary expression is 202 // permitted. For instance, the identifier f in a selector 203 // expression x.f is found only in the Selections map, the 204 // identifier z in a variable declaration 'var z int' is found 205 // only in the Defs map, and identifiers denoting packages in 206 // qualified identifiers are collected in the Uses map. 207 Types map[syntax.Expr]TypeAndValue 208 209 // If StoreTypesInSyntax is set, type information identical to 210 // that which would be put in the Types map, will be set in 211 // syntax.Expr.TypeAndValue (independently of whether Types 212 // is nil or not). 213 StoreTypesInSyntax bool 214 215 // Instances maps identifiers denoting generic types or functions to their 216 // type arguments and instantiated type. 217 // 218 // For example, Instances will map the identifier for 'T' in the type 219 // instantiation T[int, string] to the type arguments [int, string] and 220 // resulting instantiated *Named type. Given a generic function 221 // func F[A any](A), Instances will map the identifier for 'F' in the call 222 // expression F(int(1)) to the inferred type arguments [int], and resulting 223 // instantiated *Signature. 224 // 225 // Invariant: Instantiating Uses[id].Type() with Instances[id].TypeArgs 226 // results in an equivalent of Instances[id].Type. 227 Instances map[*syntax.Name]Instance 228 229 // Defs maps identifiers to the objects they define (including 230 // package names, dots "." of dot-imports, and blank "_" identifiers). 231 // For identifiers that do not denote objects (e.g., the package name 232 // in package clauses, or symbolic variables t in t := x.(type) of 233 // type switch headers), the corresponding objects are nil. 234 // 235 // For an embedded field, Defs returns the field *Var it defines. 236 // 237 // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() 238 Defs map[*syntax.Name]Object 239 240 // Uses maps identifiers to the objects they denote. 241 // 242 // For an embedded field, Uses returns the *TypeName it denotes. 243 // 244 // Invariant: Uses[id].Pos() != id.Pos() 245 Uses map[*syntax.Name]Object 246 247 // Implicits maps nodes to their implicitly declared objects, if any. 248 // The following node and object types may appear: 249 // 250 // node declared object 251 // 252 // *syntax.ImportDecl *PkgName for imports without renames 253 // *syntax.CaseClause type-specific *Var for each type switch case clause (incl. default) 254 // *syntax.Field anonymous parameter *Var (incl. unnamed results) 255 // 256 Implicits map[syntax.Node]Object 257 258 // Selections maps selector expressions (excluding qualified identifiers) 259 // to their corresponding selections. 260 Selections map[*syntax.SelectorExpr]*Selection 261 262 // Scopes maps syntax.Nodes to the scopes they define. Package scopes are not 263 // associated with a specific node but with all files belonging to a package. 264 // Thus, the package scope can be found in the type-checked Package object. 265 // Scopes nest, with the Universe scope being the outermost scope, enclosing 266 // the package scope, which contains (one or more) files scopes, which enclose 267 // function scopes which in turn enclose statement and function literal scopes. 268 // Note that even though package-level functions are declared in the package 269 // scope, the function scopes are embedded in the file scope of the file 270 // containing the function declaration. 271 // 272 // The Scope of a function contains the declarations of any 273 // type parameters, parameters, and named results, plus any 274 // local declarations in the body block. 275 // It is coextensive with the complete extent of the 276 // function's syntax ([*ast.FuncDecl] or [*ast.FuncLit]). 277 // The Scopes mapping does not contain an entry for the 278 // function body ([*ast.BlockStmt]); the function's scope is 279 // associated with the [*ast.FuncType]. 280 // 281 // The following node types may appear in Scopes: 282 // 283 // *syntax.File 284 // *syntax.FuncType 285 // *syntax.TypeDecl 286 // *syntax.BlockStmt 287 // *syntax.IfStmt 288 // *syntax.SwitchStmt 289 // *syntax.CaseClause 290 // *syntax.CommClause 291 // *syntax.ForStmt 292 // 293 Scopes map[syntax.Node]*Scope 294 295 // InitOrder is the list of package-level initializers in the order in which 296 // they must be executed. Initializers referring to variables related by an 297 // initialization dependency appear in topological order, the others appear 298 // in source order. Variables without an initialization expression do not 299 // appear in this list. 300 InitOrder []*Initializer 301 302 // FileVersions maps a file to its Go version string. 303 // If the file doesn't specify a version, the reported 304 // string is Config.GoVersion. 305 // Version strings begin with “go”, like “go1.21”, and 306 // are suitable for use with the [go/version] package. 307 FileVersions map[*syntax.PosBase]string 308 } 309 310 func (info *Info) recordTypes() bool { 311 return info.Types != nil || info.StoreTypesInSyntax 312 } 313 314 // TypeOf returns the type of expression e, or nil if not found. 315 // Precondition 1: the Types map is populated or StoreTypesInSynax is set. 316 // Precondition 2: Uses and Defs maps are populated. 317 func (info *Info) TypeOf(e syntax.Expr) Type { 318 if info.Types != nil { 319 if t, ok := info.Types[e]; ok { 320 return t.Type 321 } 322 } else if info.StoreTypesInSyntax { 323 if tv := e.GetTypeInfo(); tv.Type != nil { 324 return tv.Type 325 } 326 } 327 328 if id, _ := e.(*syntax.Name); id != nil { 329 if obj := info.ObjectOf(id); obj != nil { 330 return obj.Type() 331 } 332 } 333 return nil 334 } 335 336 // ObjectOf returns the object denoted by the specified id, 337 // or nil if not found. 338 // 339 // If id is an embedded struct field, ObjectOf returns the field (*Var) 340 // it defines, not the type (*TypeName) it uses. 341 // 342 // Precondition: the Uses and Defs maps are populated. 343 func (info *Info) ObjectOf(id *syntax.Name) Object { 344 if obj := info.Defs[id]; obj != nil { 345 return obj 346 } 347 return info.Uses[id] 348 } 349 350 // PkgNameOf returns the local package name defined by the import, 351 // or nil if not found. 352 // 353 // For dot-imports, the package name is ".". 354 // 355 // Precondition: the Defs and Implicts maps are populated. 356 func (info *Info) PkgNameOf(imp *syntax.ImportDecl) *PkgName { 357 var obj Object 358 if imp.LocalPkgName != nil { 359 obj = info.Defs[imp.LocalPkgName] 360 } else { 361 obj = info.Implicits[imp] 362 } 363 pkgname, _ := obj.(*PkgName) 364 return pkgname 365 } 366 367 // TypeAndValue reports the type and value (for constants) 368 // of the corresponding expression. 369 type TypeAndValue struct { 370 mode operandMode 371 Type Type 372 Value constant.Value 373 } 374 375 // IsVoid reports whether the corresponding expression 376 // is a function call without results. 377 func (tv TypeAndValue) IsVoid() bool { 378 return tv.mode == novalue 379 } 380 381 // IsType reports whether the corresponding expression specifies a type. 382 func (tv TypeAndValue) IsType() bool { 383 return tv.mode == typexpr 384 } 385 386 // IsBuiltin reports whether the corresponding expression denotes 387 // a (possibly parenthesized) built-in function. 388 func (tv TypeAndValue) IsBuiltin() bool { 389 return tv.mode == builtin 390 } 391 392 // IsValue reports whether the corresponding expression is a value. 393 // Builtins are not considered values. Constant values have a non- 394 // nil Value. 395 func (tv TypeAndValue) IsValue() bool { 396 switch tv.mode { 397 case constant_, variable, mapindex, value, nilvalue, commaok, commaerr: 398 return true 399 } 400 return false 401 } 402 403 // IsNil reports whether the corresponding expression denotes the 404 // predeclared value nil. Depending on context, it may have been 405 // given a type different from UntypedNil. 406 func (tv TypeAndValue) IsNil() bool { 407 return tv.mode == nilvalue 408 } 409 410 // Addressable reports whether the corresponding expression 411 // is addressable (https://golang.org/ref/spec#Address_operators). 412 func (tv TypeAndValue) Addressable() bool { 413 return tv.mode == variable 414 } 415 416 // Assignable reports whether the corresponding expression 417 // is assignable to (provided a value of the right type). 418 func (tv TypeAndValue) Assignable() bool { 419 return tv.mode == variable || tv.mode == mapindex 420 } 421 422 // HasOk reports whether the corresponding expression may be 423 // used on the rhs of a comma-ok assignment. 424 func (tv TypeAndValue) HasOk() bool { 425 return tv.mode == commaok || tv.mode == mapindex 426 } 427 428 // Instance reports the type arguments and instantiated type for type and 429 // function instantiations. For type instantiations, Type will be of dynamic 430 // type *Named. For function instantiations, Type will be of dynamic type 431 // *Signature. 432 type Instance struct { 433 TypeArgs *TypeList 434 Type Type 435 } 436 437 // An Initializer describes a package-level variable, or a list of variables in case 438 // of a multi-valued initialization expression, and the corresponding initialization 439 // expression. 440 type Initializer struct { 441 Lhs []*Var // var Lhs = Rhs 442 Rhs syntax.Expr 443 } 444 445 func (init *Initializer) String() string { 446 var buf strings.Builder 447 for i, lhs := range init.Lhs { 448 if i > 0 { 449 buf.WriteString(", ") 450 } 451 buf.WriteString(lhs.Name()) 452 } 453 buf.WriteString(" = ") 454 syntax.Fprint(&buf, init.Rhs, syntax.ShortForm) 455 return buf.String() 456 } 457 458 // Check type-checks a package and returns the resulting package object and 459 // the first error if any. Additionally, if info != nil, Check populates each 460 // of the non-nil maps in the Info struct. 461 // 462 // The package is marked as complete if no errors occurred, otherwise it is 463 // incomplete. See Config.Error for controlling behavior in the presence of 464 // errors. 465 // 466 // The package is specified by a list of *syntax.Files and corresponding 467 // file set, and the package path the package is identified with. 468 // The clean path must not be empty or dot ("."). 469 func (conf *Config) Check(path string, files []*syntax.File, info *Info) (*Package, error) { 470 pkg := NewPackage(path, "") 471 return pkg, NewChecker(conf, pkg, info).Files(files) 472 }