[Unretained] is an unsafe non-owning class/interface reference (like Swift's
unowned(unsafe)): no reference counting and no weak-table registration. The
field assignment is a plain pointer store and field cleanup is a no-op for it.
Use only when the referent is guaranteed to outlive the field.
This complements [Weak] (safe, auto-nils on referent free, has weak-registry
cost). The two are mutually exclusive on a declaration.
Pipeline:
- semantic: HasUnretainedAttribute + resolution on field decls, with
class/interface-only and not-both-with-Weak checks; IsUnretained propagated
to TFieldInfo.
- codegen: EmitFieldAssignment and the implicit-Self field path emit a bare
storel for unretained class fields; EmitFieldCleanupFn skips them.
Apply [Unretained] to the compiler's own non-owning class fields — every
field documented "not owned" across uAST (ResolvedType, ResolvedMethod,
ResolvedDecl, FieldInfo back-pointers, …) and uSymbolTable (type-desc
references, FParent back-pointers, NextOverload, …). These pointed into
the symbol table's type pool / the AST tree, which the codegen was
needlessly ARC-managing — inflating shared TTypeDesc refcounts. Marking them
unretained de-inflates those (TTypeDesc dropped from rc=4/6 toward rc=2) at
zero per-assignment cost.
Tests: 5 new cases in cp.test.weakref.pas (semantic rejection on non-class
and on [Weak]+[Unretained]; codegen asserts no addref on store, no
_WeakAssign, no release/clear in field cleanup). Docs: language-rationale
gains a [Weak] vs [Unretained] section with a comparison table.
Fixpoint clean; 2269 tests pass.