A Decl, like today, is either:
- A
struct
,union
,enum
, oropaque
(i.e. a type with a namespace) - A container-scope
const
,var
, orfn
Types are immutable. Whenever a type declaration is analyzed, it gets it from the InternPool, keyed on the current generation (so re-analysis of a type declaration across generations always creates a distinct type). The existing owner decl is used, but its value updated to refer to the new type.
(TODO: the above system will need some changes if we want structural equivalence based on captures)
Rationale: if types are not immutable, we need to recursively mark dependencies on the type from every entity which references it, which is very complex. Immutable types give us this for free, because everything which uses the type automatically becomes outdated.
Across incremental updates, we attempt to correlate ZIR instructions so as to decide the new ZIR indices of existing Decls. Notably, if a named decl is mapped, then it is guaranteed to have the same name as before and to live in the same namespace.
During semantic analysis, dependencies may be marked to trigger re-analysis of Decls and function bodies in future generations. Dependencies are marked on Sema's owner decl or function.
The "depender" of a dependency edge may be either of the following:
- a Decl
- arises when semantically analyzing the comptime-known tv of a Decl
- a runtime function (either from a non-generic function decl, or a generic instantiation)
- arises when semantically analyzing a runtime function body
The "dependee" of a dependency edge may be any of the following:
- a Decl's value
- arises from using a Decl's tv
- note that this is not a dependency on the Decl's namespace!
- outdated whenever a Decl's InternPool.Index changes, or when the Decl is removed
- arises from using a Decl's tv
- a Decl's source code
- arises from a comptime or inline call
- outdated whenever the source code corresponding to a Decl changes, or when the Decl is removed
- a function Decl's type signature source code
- arises from a runtime generic call
- outdated whenever the source code corresponding to a generic function's type signature changes, or when the Decl is removed
- this exists so that modifying the body of a runtime generic function does not force re-analysis of call sites
- the full set of names in a Decl's namespace
- arises from
@typeInfo
- outdated whenever the namespace of this Decl gains or loses any name, or when the Decl is removed
- arises from
- non-existence of a name
foo
in a Decl's namespace- arises from a failed namespace lookup (either directly or through
@hasDecl
) - outdated whenever the namespace of this Decl gains the name
foo
, or when the Decl is removed
- arises from a failed namespace lookup (either directly or through
- a runtime function's IES
- arises from resolution of an IES into a concrete error set
- outdated whenever re-analysis of a function body changes its resolved IES
Every Decl has an implicit dependency on its own source code.
Every runtime function has an explicit dependency on the source code of its owner decl. (This is made explicit because otherwise we need to be able to iterate all runtime funtions corresponding to a single Decl!)