4.4.5 类型检查器
与类型检查器相关的重要数据结构有三个,本节将分析其代码
4.4.5.1. Config
Config用来配置类型检查器,定义在$GCROOT/compile/internal/types2/api.go中:
type Config struct {
// GoVersion describes the accepted Go language version. The string
// must follow the format "go%d.%d" (e.g. "go1.12") or ist must be
// empty; an empty string indicates the latest language version.
// If the format is invalid, invoking the type checker will cause a
// panic.
GoVersion string
// If IgnoreFuncBodies is set, function bodies are not
// type-checked.
IgnoreFuncBodies bool
// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
// declares an empty "C" package and errors are omitted for qualified
// identifiers referring to package C (which won't find an object).
// This feature is intended for the standard library cmd/api tool.
//
// Caution: Effects may be unpredictable due to follow-on errors.
// Do not use casually!
FakeImportC bool
// If IgnoreLabels is set, correct label use is not checked.
// TODO(gri) Consolidate label checking and remove this flag.
IgnoreLabels bool
// If CompilerErrorMessages is set, errors are reported using
// cmd/compile error strings to match $GOROOT/test errors.
// TODO(gri) Consolidate error messages and remove this flag.
CompilerErrorMessages bool
// If go115UsesCgo is set, the type checker expects the
// _cgo_gotypes.go file generated by running cmd/cgo to be
// provided as a package source file. Qualified identifiers
// referring to package C will be resolved to cgo-provided
// declarations within _cgo_gotypes.go.
//
// It is an error to set both FakeImportC and go115UsesCgo.
go115UsesCgo bool
// If Trace is set, a debug trace is printed to stdout.
Trace bool
// If Error != nil, it is called with each error found
// during type checking; err has dynamic type Error.
// Secondary errors (for instance, to enumerate all types
// involved in an invalid recursive type declaration) have
// error strings that start with a '\t' character.
// If Error == nil, type-checking stops with the first
// error found.
Error func(err error)
// An importer is used to import packages referred to from
// import declarations.
// If the installed importer implements ImporterFrom, the type
// checker calls ImportFrom instead of Import.
// The type checker reports an error if an importer is needed
// but none was installed.
Importer Importer
// If Sizes != nil, it provides the sizing functions for package unsafe.
// Otherwise SizesFor("gc", "amd64") is used instead.
Sizes Sizes
// If DisableUnusedImportCheck is set, packages are not checked
// for unused imports.
DisableUnusedImportCheck bool
}其中各个字段的注释写得非常详细,基本都是一些开关属性。比较重要的是Importer以及Sizes, 前者是包加载器,而后者负责处理各类型的对齐问题。
4.4.5.2. Info
Info用来存放类型检查器的检查结果,定义在$GCROOT/compile/internal/types2/api.go中:
Initializer表示的是当前 package 的初始化顺序,其余的所有属性都是一个以 AST 节点为 key 的 map, 类型检查器会在类型检查的过程中收集对应的对象,Info 包含了所有类型检查的结果,其会在后续生成 IR Tree 时使用。其中涉及到的TypeAndValue以及Inferred都在本文件中定义。
4.4.5.3. Checker
类型检查的整体逻辑由Checker驱动,其定义在文件$GCROOT/compile/internal/types2/check.go中:
Checker定义了非常多的方法,几乎包含了所有的类型检查逻辑,而其属性封装了类型检查需要的各种数据结构,包括用于存放各种中间状态的属性,其中有几个属性还需要单独介绍一下:
declInfo
该结构用来封装 package-level 的顶级申明,与 AST 中的“申明(Declaration)”对应。其定义在文件$GCROOT/compile/internal/types2/resolver.go中:
其内部封装了一个申明的各个语法树节点,类型检查主要围绕这个结构体展开。其中deps属性用来保存当前 declInfo 所依赖的对象,用于构建初始化顺序。
delayed & finals
类型检查是分阶段进行的,有些模块的工作需要依赖其他部分的检查结果,这两个属性用来保存该类工作,所以其是两个函数列表。该属性在类型检查逻辑中会有使用。
最后更新于
这有帮助吗?