aboutsummaryrefslogtreecommitdiff
path: root/notes/ffi_safety.txt
blob: 5630683f8329d55331ed72893f84022239749687 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

SLUL can in theory do safe FFI, "as long as the other side does it the
same way".

Type constraints:

    All types
        Must be initialized.
        Alignment padding must be bitwise 0 (is this realistic to enforce?
        maybe there should be a `calloc_as_uninitialized`)

    (short)
    int
    long
        Must be non-negative, unless marked with `signed` qualifier.
        If there's a range constraint, then it must be in range.

    Obj
        References are non-nullable by default.
        References must point to valid data (i.e. ).
        All fields must be initialized.
        Anything that is referenced must be valid.
        No other reference to the object may be `var` unless ALL references
        are `shared`.

    non-shared non-var Obj
        Must not be modified at all

    non-shared Obj
        Must not be modified by anyone else.

    !Obj
        Modifiable objects must have at most one reference to them.

    non-closed enum
        Enum must have one of the enum values in any version (i.e. the enum
        could originate from a future version).

    closed enum
        Enum must have one of the enum values.
        No more values may be added in future versions.

    string
        Is immutable.

Language specific stuff
-----------------------

C can support all of this, but C as always does not restrict itself to
safe operations, so UB is possible.

Rust currently still lacks a safe ABI as far as I know, so it can still have
UB. But there are (at least) three fundamental differences in SLUL vs Rust:

* The `shared` type qualifier doesn't have any equivalent in Rust.
* In SLUL, the last reference to an object can be removed without any
  subsequent action. It will leak for a time and eventually get cleaned up
  by either GC (if in use) or the later by the arena alloactor.
* Neither non-closed nor closed enums have any equivalent in Rust.
  They only map to Rust enums (without the sum type / union part) in the
  following two cases:
    - When the enum is not part of API (in which case it is uninteresting
      for FFI anyway).
    - When the enum definition cannot ever change in future versions.
      (I.e. SLUL implicitly has a soundness constraint on library changes,
      that cannot be expressed in Rust.)