aboutsummaryrefslogtreecommitdiffhomepage
path: root/notes/automatic_ref_types.txt
blob: 7f42b58f9c9e5323731746835a79c0d57170f3cb (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

Automatic ref/stack type selection
==================================

See also:
- usability_improvements.txt
- automatic_deref_ux.txt

Select between ref/copy automatically when it does not matter which one is
used.

It could also be used to shorten the syntax for var parameters (including the
implicit "this" parameter).

Note that copying ONLY works with:
- non-private types, or
- private types in private contexts in the same module
  (e.g. private functions)
and it does NOT work with:
- aliased/threaded qualifiers
- if the object has some kind of "identity" which is decided by the address.

And there are limitations of automatic parameters:
- they cannot be assigned to a reference that has a longer lifetime than
  the function itself, or that require a target with "identity" based on
  the address.

Note that small structs (that get copied) can still contain references to
things with lifetime bounds. So it is in fact meaningful to have lifetime
bounds on non-ref types!

Overview
--------
Will it work?

* Function parameters/return values
    - Yes, it should work
* Struct fields
    - Possibly, but it might be a bad idea.
* Local variables
    - Yes, it should work (with reference + backing values)
* Global constant data
    - Yes, because references aren't allowed here anyway
      so there is only one case to handle.

So "struct fields" is the only case were it probably is tricky / a bad idea.

Function parameters/return values
---------------------------------

    func SomeThing.work(OtherThing o) -> ReturnThing

        - this:     can be ref or copy
        - o:        can be ref or copy
        - return:   copy*

        * it is semantically copy, but because SLUL uses the C ABI, it is
          probably implemented as a pointer if the value does not fit in
          a register.

    func var SomeThing.work(var OtherThing o) -> var ReturnThing

        - this:     will be ref**
        - o:        will be ref**
        - return    copy*

        ** if the ABI has multiple return registers, and passes small
           results of variable parameters in output registers, it could
           be passed asa registers.

Struct fields
-------------
This could possibly work, but is it a good idea?
- it requires an additional indirection
- the field must be initialized:
    - either to a reference to a value with where the effective lifetime
      is "lifetime the_value >= the_struct"
    - or to a newly allocated item, in the same arena as the struct.
- the data structure is no longer explicitly defined
  (it can have implicit indirection or implicit copying)

So assigning to an uninitialized field could trigger arena allocation!
Should it even be allowed to do it with the "=" operator, or should there
be a separate operator? Or a built-in function, e.g:
    somestruct.field = maybe_alloc_copy(thevalue)
    somestruct.field = transfer(arena, thevalue)  # alternative name

Note that maybe_alloc_copy/transfer is a shallow copy!
(It cannot be a deep copy if the struct can contain references to
private types)

Local variables
---------------
Local variables can be turned references if:
- only initialized with references to immutable data
  (and never from e.g. a function return value, or assinged a "ref var")

Alternatively, it is possible to split local variables into two:
- a reference
- a backing value, that is used when a copy operation would normally have
  occurred. In this case, the backing value is assigned, and then the
  reference is set to point to the backing value.
    - If the reference is never used, then it can be elimitated.
    - If the backing value is never used, then it can be elimitated.

The alternative solution is probably better. And it is fairly simple.

"data" / global constant data
-----------------------------
These cannot be references at all.