-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(engine/deps): preserve definitions order whenever possible #1151
base: main
Are you sure you want to change the base?
Conversation
1ed3e2a
to
7041ef6
Compare
@W95Psp please reference the issue that this is closing |
In most of the backends, a top-level definition should come prior to it's use. This is not true in Rust. Thus, we need to sort the items so that item `a` comes before it is used in another item `b`. We used to do that with a topological sort with the ocamlgraph library. But since this topological sort operated on a graph, we were loosing the original order of items. This commit now: - construct a the transtive closure of the dependency graph - use this closure to stable sort the items The comparison function is defined as follows (`g` denotes the transitive closure): 1. if there is an edge `a ⟶ b` in `g` and an edge `b ⟶ a`, we are in a recursive bundle, hence we return `0`: `a` equals `b` 2. if there is an edge `a ⟶ b` in `g`, we return `-1` 2. if there is an edge `b ⟶ a` in `g`, we return `1` 2. otherwise there is no relation between `a` and `b`, we return `0`
7041ef6
to
aa33ea4
Compare
I hit this issue again yesterday when working on Bertie. Things were reordered with every change I made to some modules, for no good reason. I believe it also makes it hard to diff and debug the effect of engine changes (since the order change would make the diffs look much bigger than they are). So I encourage converting this into a reviewable PR whenever some other work item needs it. |
I tried fixing this PR today. The first problem with it is the following: fn f() {h()}
fn g() {}
fn h(){f()} Open this code snippet in the playground fn no_dependency_1() {}
fn f() {g()}
fn no_dependency_2() {}
fn g() {} Open this code snippet in the playground This means we can either implement our own sort that solves this issue (something like https://blog.gapotchenko.com/stable-topological-sort). Or use the solution of #1140 (using ocamlgraph stable topological sort with the original ordering passed as a comparison function). Note that the specs of this are a bit different from what we want (it doesn't guarantee to keep cycles together), but the implementation corresponds to what we want (but we should make sure that this doesn't change). |
In most of the backends, a top-level definition should come prior to it's use. This is not true in Rust.
Thus, we need to sort the items so that item
a
comes before it is used in another itemb
.We used to do that with a topological sort with the ocamlgraph library. But since this topological sort operated on a graph, we were loosing the original order of items.
This commit now:
The comparison function is defined as follows (
g
denotes the transitive closure):a ⟶ b
ing
and an edgeb ⟶ a
, we are in a recursive bundle, hence we return0
:a
equalsb
a ⟶ b
ing
, we return-1
b ⟶ a
ing
, we return1
a
andb
, we return0
The run for this PR on libcrux is there: