mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Smart casts and control flow graph
With the introduction of nullable types, we want the compiler to be smart in cases like > if (x == null) return; > // x is int now or > if (x == null) x = 0; > // x is int now These are called smart casts: when the type of variable at particular usage might differ from its declaration. Implementing smart casts is very challenging. They are based on building control-flow graph and handling every AST vertex with care. Actually, I represent cfg not a as a "graph with edges". Instead, it's a "structured DFS" for the AST: 1) at every point of inferring, we have "current flow facts" 2) when we see an `if (...)`, we create two derived contexts 3) after `if`, finalize them at the end and unify 4) if we detect unreachable code, we mark that context In other words, we get the effect of a CFG but in a more direct approach. That's enough for AST-level data-flow. Smart casts work for local variables and tensor/tuple indices. Compilation errors have been reworked and now are more friendly. There are also compilation warnings for always true/false conditions inside if, assert, etc.
This commit is contained in:
parent
f3e620f48c
commit
7bcb8b895f
47 changed files with 3057 additions and 833 deletions
|
@ -409,6 +409,27 @@ public:
|
|||
bool can_be_casted_with_as_operator(TypePtr cast_to) const override;
|
||||
};
|
||||
|
||||
/*
|
||||
* `never` is a special type meaning "no value can be hold".
|
||||
* Is may appear due to smart casts, for example `if (x == null && x != null)` makes x "never".
|
||||
* Functions returning "never" assume to never exit, calling them interrupts control flow.
|
||||
* Such variables can not be cast to any other types, all their usage will trigger type mismatch errors.
|
||||
*/
|
||||
class TypeDataNever final : public TypeData {
|
||||
TypeDataNever() : TypeData(19ULL, 0, 0) {}
|
||||
|
||||
static TypePtr singleton;
|
||||
friend void type_system_init();
|
||||
|
||||
public:
|
||||
static TypePtr create() { return singleton; }
|
||||
|
||||
std::string as_human_readable() const override { return "never"; }
|
||||
bool can_rhs_be_assigned(TypePtr rhs) const override;
|
||||
bool can_be_casted_with_as_operator(TypePtr cast_to) const override;
|
||||
bool can_hold_tvm_null_instead() const override;
|
||||
};
|
||||
|
||||
/*
|
||||
* `void` is TypeDataVoid.
|
||||
* From the type system point of view, `void` functions return nothing.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue