spicy
spicy copied to clipboard
Add validation checking that modules of used external identifiers are imported
We currently allow the implementation of hooks defined in another module without requiring the module to be imported, e.g., given a module a
# a.hlt
module a {
import hilti;
declare public hook void h();
h();
function hook void h() { hilti::print("a::h (a)"); }
}
we can declare a module b
# b.hlt
module b {
# `a` not explicitly imported.
import hilti;
public type a = struct {
hook void h();
};
# Implementation for undeclared hook from module `a`.
function hook void a::h() { hilti::print("a::h (b)"); }
method hook void a::h() { hilti::print("b::a::h"); }
global b::a x;
x.h();
}
If we compile b.hlt with a.hlt the hook declaration from a becomes visible and produces the expected output,
$ hiltic -j b.hlt a.hlt
b::a::h
a::h (b)
a::h (a)
If we compile b.hlt standalone the undeclared hook is not diagnosed,
$ hiltic b.hlt -j
b::a::h
Above example contains another twist in that if b.hlt actually contained an import a; a redefinition error would be triggered
$ hiltic b.hlt -j
[error] b.hlt:6:1-8:3: redefinition of 'a' defined in b.hlt:4:1
[error] hiltic: aborting after errors
In order to make e.g., codegen more deterministic we should probably make an explicit import mandatory when accessing external names.