Check runs the package through the typechecker. The package must already be loaded and all dependencies must have been checked already. Idempotent.
()
| 384 | // |
| 385 | // Idempotent. |
| 386 | func (p *Package) Check() error { |
| 387 | if p.Pkg != nil { |
| 388 | return nil // already typechecked |
| 389 | } |
| 390 | |
| 391 | // Prepare some state used during type checking. |
| 392 | var typeErrors []error |
| 393 | checker := p.program.typeChecker // make a copy, because it will be modified |
| 394 | checker.Error = func(err error) { |
| 395 | typeErrors = append(typeErrors, err) |
| 396 | } |
| 397 | checker.Importer = p |
| 398 | if p.Module.GoVersion != "" { |
| 399 | // Setting the Go version for a module makes sure the type checker |
| 400 | // errors out on language features not supported in that particular |
| 401 | // version. |
| 402 | checker.GoVersion = "go" + p.Module.GoVersion |
| 403 | } else { |
| 404 | // Version is not known, so use the currently installed Go version. |
| 405 | // This is needed for `tinygo run` for example. |
| 406 | // Normally we'd use goenv.GorootVersionString(), but for compatibility |
| 407 | // with Go 1.20 and below we need a version in the form of "go1.12" (no |
| 408 | // patch version). |
| 409 | major, minor, err := goenv.GetGorootVersion() |
| 410 | if err != nil { |
| 411 | return err |
| 412 | } |
| 413 | checker.GoVersion = fmt.Sprintf("go%d.%d", major, minor) |
| 414 | } |
| 415 | initFileVersions(&p.info) |
| 416 | |
| 417 | // Do typechecking of the package. |
| 418 | packageName := p.ImportPath |
| 419 | if p == p.program.MainPkg() { |
| 420 | if p.Name != "main" { |
| 421 | return Errors{p, []error{ |
| 422 | scanner.Error{ |
| 423 | Pos: p.program.fset.Position(p.Files[0].Name.Pos()), |
| 424 | Msg: fmt.Sprintf("expected main package to have name \"main\", not %#v", p.Name), |
| 425 | }, |
| 426 | }} |
| 427 | } |
| 428 | packageName = "main" |
| 429 | } |
| 430 | typesPkg, err := checker.Check(packageName, p.program.fset, p.Files, &p.info) |
| 431 | if err != nil { |
| 432 | if err, ok := err.(Errors); ok { |
| 433 | return err |
| 434 | } |
| 435 | if len(typeErrors) != 0 { |
| 436 | // Got type errors, so return them. |
| 437 | return Errors{p, typeErrors} |
| 438 | } |
| 439 | // This can happen in some weird cases. |
| 440 | // The only case I know is when compiling a Go 1.23 program, with a |
| 441 | // TinyGo version that supports Go 1.23 but is compiled using Go 1.22. |
| 442 | // So this should be pretty rare. |
| 443 | return Errors{p, []error{err}} |