Skip to content
← Back

src/syntax/process/check_pure_overrides.ghul

1
namespace Syntax.Process is
2
use Logging;
3
use Trees;
4
use Source;
5
6
// Enforces the pure-override contract after infer-store-free has
7
// settled the store-free bits: a function that overrides or
8
// implements a declared-pure base must itself be pure — declared
9
// or proven. The declared bit on the base is what call sites
10
// trust across dispatch, including dispatch to overrides this
11
// compilation is introducing, so an unprovable, undeclared
12
// override is a hole in that trust and is rejected. Bases can be
13
// local or imported: a PURE_ATTRIBUTE read on import marks the
14
// reflected base declared-pure, so overriding a pure member from
15
// another assembly is checked here in the overriding assembly.
16
class CHECK_PURE_OVERRIDES: ScopedVisitor is
17
_logger: Logger;
18
19
init(
20
logger: Logger,
21
symbol_table: Semantic.SYMBOL_TABLE,
22
namespaces: Semantic.NAMESPACES
23
)
24
is
25
super.init(logger, symbol_table, namespaces);
26
27
_logger = logger;
28
si
29
30
apply(root: Trees.Node) is
31
root.walk(self);
32
si
33
34
visit(function: Definitions.FUNCTION) is
35
super.visit(function);
36
37
let symbol = symbol_for(function);
38
39
if !symbol? \/ !isa Semantic.Symbols.Function(symbol) then
40
return;
41
fi
42
43
let function_symbol = cast Semantic.Symbols.Function(symbol);
44
45
let overridees = function_symbol.overridees;
46
47
if !overridees? \/ function_symbol.is_store_free then
48
return;
49
fi
50
51
for base in overridees do
52
if isa Semantic.Symbols.Function(base) /\ (cast Semantic.Symbols.Function(base)).is_declared_pure then
53
_logger.error(
54
function.name!.location,
55
"{function_symbol.name} overrides pure {base.qualified_name} so must be declared pure or provably store-free"
56
);
57
58
return;
59
fi
60
od
61
si
62
si
63
si