pub struct Checker<'a, S: SourceRead> {
pub tc_objs: &'a mut TCObjects,
pub ast_objs: &'a mut AstObjects,
pub fset: &'a mut FileSet,
pub all_pkgs: &'a mut Map<String, PackageKey>,
pub pkg: PackageKey,
pub obj_map: Map<ObjKey, DeclInfoKey>,
pub imp_map: Map<ImportKey, PackageKey>,
pub octx: ObjContext,
pub result: TypeInfo,
pub indent: Rc<RefCell<usize>>,
/* private fields */
}Fields§
§tc_objs: &'a mut TCObjects§ast_objs: &'a mut AstObjects§fset: &'a mut FileSet§all_pkgs: &'a mut Map<String, PackageKey>§pkg: PackageKey§obj_map: Map<ObjKey, DeclInfoKey>§imp_map: Map<ImportKey, PackageKey>§octx: ObjContext§result: TypeInfo§indent: Rc<RefCell<usize>>Implementations§
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn unparen(x: &Expr) -> &Expr
Sourcepub fn invalid_ast(&self, pos: Pos, err: &str)
pub fn invalid_ast(&self, pos: Pos, err: &str)
invalid_ast helps to report ast error
pub fn invalid_arg(&self, pos: Pos, err: &str)
pub fn invalid_op(&self, pos: Pos, err: &str)
pub fn obj_path_str(&self, path: &Vec<ObjKey>) -> String
pub fn dump(&self, pos: Option<Pos>, msg: &str)
pub fn print_trace(&self, pos: Pos, msg: &str)
pub fn trace_begin(&self, pos: Pos, msg: &str)
pub fn trace_end(&self, pos: Pos, msg: &str)
pub fn has_cycle(&self, okey: ObjKey, path: &[ObjKey], report: bool) -> bool
pub fn comma_ok_type( tc_objs: &mut TCObjects, pos: usize, pkg: PackageKey, t: &[TypeKey; 2], ) -> TypeKey
pub fn unpack<'b>( &mut self, rhs: &'b Vec<Expr>, lhs_len: usize, allow_comma_ok: bool, variadic: bool, fctx: &mut FilesContext<'_, S>, ) -> UnpackResult<'b>
pub fn use_exprs(&mut self, exprs: &Vec<Expr>, fctx: &mut FilesContext<'_, S>)
pub fn use_lhs(&mut self, lhs: &Vec<Expr>, fctx: &mut FilesContext<'_, S>)
pub fn lookup(&self, name: &str) -> Option<ObjKey>
pub fn add_decl_dep(&mut self, to: ObjKey)
pub fn insert_obj_to_set( &self, set: &mut Map<String, ObjKey>, okey: ObjKey, ) -> Option<ObjKey>
pub fn ast_ident(&self, key: IdentKey) -> &Ident
pub fn lobj(&self, key: ObjKey) -> &LangObj
pub fn lobj_mut(&mut self, key: ObjKey) -> &mut LangObj
pub fn otype(&self, key: TypeKey) -> &Type
pub fn otype_mut(&mut self, key: TypeKey) -> &mut Type
pub fn otype_interface(&self, key: TypeKey) -> &InterfaceDetail
pub fn otype_signature(&self, key: TypeKey) -> &SignatureDetail
pub fn otype_interface_mut(&mut self, key: TypeKey) -> &mut InterfaceDetail
pub fn otype_signature_mut(&mut self, key: TypeKey) -> &mut SignatureDetail
pub fn package(&self, key: PackageKey) -> &Package
pub fn package_mut(&mut self, key: PackageKey) -> &mut Package
pub fn scope(&self, key: ScopeKey) -> &Scope
pub fn decl_info(&self, key: DeclInfoKey) -> &DeclInfo
pub fn position(&self, pos: Pos) -> FilePos
pub fn builtin_info(&self, id: Builtin) -> &BuiltinInfo
pub fn basic_type(&self, t: BasicType) -> TypeKey
pub fn invalid_type(&self) -> TypeKey
pub fn new_dis<'b>(&'b self, x: &'b impl Display) -> Displayer<'b>
pub fn new_td_o<'t>(&'t self, t: &'t Option<TypeKey>) -> Displayer<'t>
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Sourcepub fn assignment(
&mut self,
x: &mut Operand,
t: Option<TypeKey>,
note: &str,
fctx: &mut FilesContext<'_, S>,
)
pub fn assignment( &mut self, x: &mut Operand, t: Option<TypeKey>, note: &str, fctx: &mut FilesContext<'_, S>, )
assignment reports whether x can be assigned to a variable of type t, if necessary by attempting to convert untyped values to the appropriate type. context describes the context in which the assignment takes place. Use t == None to indicate assignment to an untyped blank identifier. x.mode is set to invalid if the assignment failed.
pub fn init_const( &mut self, lhskey: ObjKey, x: &mut Operand, fctx: &mut FilesContext<'_, S>, )
pub fn init_var( &mut self, lhskey: ObjKey, x: &mut Operand, msg: &str, fctx: &mut FilesContext<'_, S>, ) -> Option<TypeKey>
pub fn assign_var( &mut self, lhs: &Expr, x: &mut Operand, fctx: &mut FilesContext<'_, S>, ) -> Option<TypeKey>
Sourcepub fn init_vars(
&mut self,
lhs: &Vec<ObjKey>,
rhs: &Vec<Expr>,
return_pos: Option<Pos>,
fctx: &mut FilesContext<'_, S>,
)
pub fn init_vars( &mut self, lhs: &Vec<ObjKey>, rhs: &Vec<Expr>, return_pos: Option<Pos>, fctx: &mut FilesContext<'_, S>, )
If return_pos is_some, init_vars is called to type-check the assignment of return expressions, and return_pos is the position of the return statement.
pub fn assign_vars( &mut self, lhs: &Vec<Expr>, rhs: &Vec<Expr>, fctx: &mut FilesContext<'_, S>, )
pub fn short_var_decl( &mut self, lhs: &Vec<Expr>, rhs: &Vec<Expr>, pos: Pos, fctx: &mut FilesContext<'_, S>, )
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Sourcepub fn builtin(
&mut self,
x: &mut Operand,
call: &Rc<CallExpr>,
id: Builtin,
fctx: &mut FilesContext<'_, S>,
) -> bool
pub fn builtin( &mut self, x: &mut Operand, call: &Rc<CallExpr>, id: Builtin, fctx: &mut FilesContext<'_, S>, ) -> bool
builtin type-checks a call to the built-in specified by id and reports whether the call is valid, with *x holding the result; but x.expr is not set. If the call is invalid, the result is false, and *x is undefined.
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn call( &mut self, x: &mut Operand, e: &Rc<CallExpr>, fctx: &mut FilesContext<'_, S>, ) -> ExprKind
Sourcepub fn arguments(
&mut self,
x: &mut Operand,
call: &CallExpr,
sig: TypeKey,
re: &UnpackedResultLeftovers<'_>,
n: usize,
fctx: &mut FilesContext<'_, S>,
)
pub fn arguments( &mut self, x: &mut Operand, call: &CallExpr, sig: TypeKey, re: &UnpackedResultLeftovers<'_>, n: usize, fctx: &mut FilesContext<'_, S>, )
arguments checks argument passing for the call with the given signature.
pub fn selector( &mut self, x: &mut Operand, e: &Rc<SelectorExpr>, fctx: &mut FilesContext<'_, S>, )
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn new( tc_objs: &'a mut TCObjects, ast_objs: &'a mut AstObjects, fset: &'a mut FileSet, errors: &'a ErrorList, pkgs: &'a mut Map<String, PackageKey>, all_results: &'a mut Map<PackageKey, TypeInfo>, pkg: PackageKey, cfg: &'a TraceConfig, reader: &'a S, ) -> Checker<'a, S>
pub fn check(self, files: Vec<File>) -> Result<PackageKey, ()>
pub fn errors(&self) -> &ErrorList
pub fn trace(&self) -> bool
pub fn new_importer(&mut self, pos: Pos) -> Importer<'_, S>
pub fn error(&self, pos: Pos, err: String)
pub fn error_str(&self, pos: Pos, err: &str)
pub fn soft_error(&self, pos: Pos, err: String)
pub fn soft_error_str(&self, pos: Pos, err: &str)
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn conversion( &mut self, x: &mut Operand, t: TypeKey, fctx: &mut FilesContext<'_, S>, )
pub fn convertable_to( &mut self, x: &Operand, t: TypeKey, fctx: &mut FilesContext<'_, S>, ) -> bool
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn report_alt_decl(&self, okey: ObjKey)
pub fn declare( &mut self, skey: ScopeKey, ikey: Option<IdentKey>, okey: ObjKey, pos: Pos, )
pub fn obj_decl( &mut self, okey: ObjKey, def: Option<TypeKey>, fctx: &mut FilesContext<'_, S>, )
Sourcepub fn invalid_type_cycle(
&self,
okey: ObjKey,
fctx: &mut FilesContext<'_, S>,
) -> bool
pub fn invalid_type_cycle( &self, okey: ObjKey, fctx: &mut FilesContext<'_, S>, ) -> bool
invalid_type_cycle returns true if the cycle starting with obj is invalid and reports an error.
pub fn const_decl( &mut self, okey: ObjKey, typ: &Option<Expr>, init: &Option<Expr>, fctx: &mut FilesContext<'_, S>, )
pub fn var_decl( &mut self, okey: ObjKey, lhs: Option<&Vec<ObjKey>>, typ: &Option<Expr>, init: &Option<Expr>, fctx: &mut FilesContext<'_, S>, )
pub fn type_decl( &mut self, okey: ObjKey, typ: &Expr, def: Option<TypeKey>, alias: bool, fctx: &mut FilesContext<'_, S>, )
pub fn func_decl( &mut self, okey: ObjKey, dkey: DeclInfoKey, fctx: &mut FilesContext<'_, S>, )
pub fn add_method_decls(&mut self, okey: ObjKey, fctx: &mut FilesContext<'_, S>)
pub fn decl_stmt(&mut self, decl: Decl, fctx: &mut FilesContext<'_, S>)
Source§impl<'a, S: SourceRead> Checker<'a, S>
Basic algorithm:
impl<'a, S: SourceRead> Checker<'a, S>
Basic algorithm:
Expressions are checked recursively, top down. Expression checker functions are generally of the form:
fn f(x &mut operand, e &Expr, …)
where e is the expression to be checked, and x is the result of the check. The check performed by f may fail in which case x.mode == OperandMode::invalid, and related error messages will have been issued by f.
If a hint argument is present, it is the composite literal element type of an outer composite literal; it is used to type-check composite literal elements that have no explicit type specification in the source (e.g.: []T{{…}, {…}}, the hint is the type T in this case).
All expressions are checked via raw_expr, which dispatches according to expression kind. Upon returning, raw_expr is recording the types and constant values for all expressions that have an untyped type (those types may change on the way up in the expression tree). Usually these are constants, but the results of comparisons or non-constant shifts of untyped constants may also be untyped, but not constant.
Untyped expressions may eventually become fully typed (i.e., not untyped), typically when the value is assigned to a variable, or is used otherwise. The update_expr_type method is used to record this final type and update the recorded types: the type-checked expression tree is again traversed down, and the new type is propagated as needed. Untyped constant expression values that become fully typed must now be representable by the full type (constant sub-expression trees are left alone except for their roots). This mechanism ensures that a client sees the actual (run-time) type an untyped value would have. It also permits type-checking of lhs shift operands “as if the shift were not present”: when update_expr_type visits an untyped lhs shift operand and assigns it it’s final type, that type must be an integer type, and a constant lhs must be representable as an integer.
When an expression gets its final type, either on the way out from raw_expr, on the way down in update_expr_type, or at the end of the type checker run, the type (and constant value, if any) is recorded via Info.Types, if present.
Sourcepub fn representable(&mut self, x: &mut Operand, t: TypeKey)
pub fn representable(&mut self, x: &mut Operand, t: TypeKey)
representable checks that a constant operand is representable in the given basic type.
Sourcepub fn update_expr_type(
&mut self,
e: &Expr,
t: TypeKey,
final_: bool,
fctx: &mut FilesContext<'_, S>,
)
pub fn update_expr_type( &mut self, e: &Expr, t: TypeKey, final_: bool, fctx: &mut FilesContext<'_, S>, )
update_expr_type updates the type of x to typ and invokes itself recursively for the operands of x, depending on expression kind. If typ is still an untyped and not the final type, update_expr_type only updates the recorded untyped type for x and possibly its operands. Otherwise (i.e., typ is not an untyped type anymore, or it is the final type for x), the type and value are recorded. Also, if x is a constant, it must be representable as a value of typ, and if x is the (formerly untyped) lhs operand of a non-constant shift, it must be an integer value.
Sourcepub fn convert_untyped(
&mut self,
x: &mut Operand,
target: TypeKey,
fctx: &mut FilesContext<'_, S>,
)
pub fn convert_untyped( &mut self, x: &mut Operand, target: TypeKey, fctx: &mut FilesContext<'_, S>, )
convert_untyped attempts to set the type of an untyped value to the target type.
pub fn comparison( &mut self, x: &mut Operand, y: &Operand, op: &Token, fctx: &mut FilesContext<'_, S>, )
Sourcepub fn binary(
&mut self,
x: &mut Operand,
e: Option<&Expr>,
lhs: &Expr,
rhs: &Expr,
op: &Token,
fctx: &mut FilesContext<'_, S>,
)
pub fn binary( &mut self, x: &mut Operand, e: Option<&Expr>, lhs: &Expr, rhs: &Expr, op: &Token, fctx: &mut FilesContext<'_, S>, )
The binary expression e may be None. It’s passed in for better error messages only.
Sourcepub fn index(
&mut self,
index: &Expr,
max: Option<u64>,
fctx: &mut FilesContext<'_, S>,
) -> Result<Option<u64>, ()>
pub fn index( &mut self, index: &Expr, max: Option<u64>, fctx: &mut FilesContext<'_, S>, ) -> Result<Option<u64>, ()>
index checks an index expression for validity. max is the upper bound for index. returns the value of the index when it’s a constant, returns None if it’s not
Sourcepub fn raw_expr(
&mut self,
x: &mut Operand,
e: &Expr,
hint: Option<TypeKey>,
fctx: &mut FilesContext<'_, S>,
) -> ExprKind
pub fn raw_expr( &mut self, x: &mut Operand, e: &Expr, hint: Option<TypeKey>, fctx: &mut FilesContext<'_, S>, ) -> ExprKind
raw_expr typechecks expression e and initializes x with the expression value or type. If an error occurred, x.mode is set to invalid. If hint is_some(), it is the type of a composite literal element.
Sourcepub fn type_assertion(
&mut self,
pos: Option<Pos>,
x: &mut Operand,
xtype: TypeKey,
t: TypeKey,
fctx: &mut FilesContext<'_, S>,
)
pub fn type_assertion( &mut self, pos: Option<Pos>, x: &mut Operand, xtype: TypeKey, t: TypeKey, fctx: &mut FilesContext<'_, S>, )
type_assertion checks that x.(T) is legal; xtyp must be the type of x.
pub fn single_value(&self, x: &mut Operand)
Sourcepub fn expr(
&mut self,
x: &mut Operand,
e: &Expr,
fctx: &mut FilesContext<'_, S>,
)
pub fn expr( &mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<'_, S>, )
expr typechecks expression e and initializes x with the expression value. The result must be a single value. If an error occurred, x.mode is set to invalid.
Sourcepub fn multi_expr(
&mut self,
x: &mut Operand,
e: &Expr,
fctx: &mut FilesContext<'_, S>,
)
pub fn multi_expr( &mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<'_, S>, )
multi_expr is like expr but the result may be a multi-value.
Sourcepub fn expr_or_type(
&mut self,
x: &mut Operand,
e: &Expr,
fctx: &mut FilesContext<'_, S>,
)
pub fn expr_or_type( &mut self, x: &mut Operand, e: &Expr, fctx: &mut FilesContext<'_, S>, )
expr_or_type typechecks expression or type e and initializes x with the expression value or type. If an error occurred, x.mode is set to invalid.
Sourcepub fn expr_with_hint(
&mut self,
x: &mut Operand,
e: &Expr,
hint: TypeKey,
fctx: &mut FilesContext<'_, S>,
)
pub fn expr_with_hint( &mut self, x: &mut Operand, e: &Expr, hint: TypeKey, fctx: &mut FilesContext<'_, S>, )
expr_with_hint typechecks expression e and initializes x with the expression value; hint is the type of a composite literal element. If an error occurred, x.mode is set to invalid.
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn init_order(&mut self)
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Sourcepub fn info_from_type_lit(
&self,
skey: ScopeKey,
iface: &Rc<InterfaceType>,
tname: Option<ObjKey>,
path: &Vec<ObjKey>,
fctx: &mut FilesContext<'_, S>,
) -> Option<Rc<IfaceInfo>>
pub fn info_from_type_lit( &self, skey: ScopeKey, iface: &Rc<InterfaceType>, tname: Option<ObjKey>, path: &Vec<ObjKey>, fctx: &mut FilesContext<'_, S>, ) -> Option<Rc<IfaceInfo>>
info_from_type_lit computes the method set for the given interface iface declared in scope. If a corresponding type name exists (tname is_some), it is used for cycle detection and to cache the method set. The result is the method set, or None if there is a cycle via embedded interfaces. A is_some result doesn’t mean that there were no errors, but they were either reported (e.g., blank methods), or will be found (again) when computing the interface’s type. If tname is not None it must be the last element in path.
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
pub fn collect_objects(&mut self, fctx: &mut FilesContext<'_, S>)
Sourcepub fn package_objects(&mut self, fctx: &mut FilesContext<'_, S>)
pub fn package_objects(&mut self, fctx: &mut FilesContext<'_, S>)
package_objects typechecks all package objects, but not function bodies.
Sourcepub fn unused_imports(&mut self, fctx: &mut FilesContext<'_, S>)
pub fn unused_imports(&mut self, fctx: &mut FilesContext<'_, S>)
unused_imports checks for unused imports.
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Source§impl<'a, S: SourceRead> Checker<'a, S>
impl<'a, S: SourceRead> Checker<'a, S>
Sourcepub fn ident(
&mut self,
x: &mut Operand,
ikey: IdentKey,
def: Option<TypeKey>,
want_type: bool,
fctx: &mut FilesContext<'_, S>,
)
pub fn ident( &mut self, x: &mut Operand, ikey: IdentKey, def: Option<TypeKey>, want_type: bool, fctx: &mut FilesContext<'_, S>, )
ident type-checks identifier ikey and initializes x with the value or type of ikey. If an error occurred, x.mode is set to invalid. For the meaning of def, see Checker.defined_type, below. If want_type is set, the identifier e is expected to denote a type.
Sourcepub fn type_expr(&mut self, e: &Expr, fctx: &mut FilesContext<'_, S>) -> TypeKey
pub fn type_expr(&mut self, e: &Expr, fctx: &mut FilesContext<'_, S>) -> TypeKey
type_expr type-checks the type expression e and returns its type, or Invalid Type.
Sourcepub fn defined_type(
&mut self,
e: &Expr,
def: Option<TypeKey>,
fctx: &mut FilesContext<'_, S>,
) -> TypeKey
pub fn defined_type( &mut self, e: &Expr, def: Option<TypeKey>, fctx: &mut FilesContext<'_, S>, ) -> TypeKey
defined_type is like type_expr but also accepts a type name def. If def is_some(), e is the type specification for the defined type def, declared in a type declaration, and def.underlying will be set to the type of e before any components of e are type-checked.
Sourcepub fn indirect_type(
&mut self,
e: &Expr,
fctx: &mut FilesContext<'_, S>,
) -> TypeKey
pub fn indirect_type( &mut self, e: &Expr, fctx: &mut FilesContext<'_, S>, ) -> TypeKey
indirect_type is like type_expr but it also breaks the (otherwise) infinite size of recursivetypes by introducing an indirection. It should be called for components of types that are not laid out in place in memory, such as pointer base types, slice or map element types, function parameter types, etc.
Sourcepub fn func_type(
&mut self,
recv: Option<&FieldList>,
ftype: FuncTypeKey,
fctx: &mut FilesContext<'_, S>,
) -> TypeKey
pub fn func_type( &mut self, recv: Option<&FieldList>, ftype: FuncTypeKey, fctx: &mut FilesContext<'_, S>, ) -> TypeKey
func_type type-checks a function or method type.
Sourcepub fn type_or_nil(
&mut self,
e: &Expr,
fctx: &mut FilesContext<'_, S>,
) -> Option<TypeKey>
pub fn type_or_nil( &mut self, e: &Expr, fctx: &mut FilesContext<'_, S>, ) -> Option<TypeKey>
type_or_nil type-checks the type expression (or nil value) e and returns the typ of e, or None. If e is neither a type nor nil, typOrNil returns Typ[Invalid].