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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//! Phase-D `Trace` implementations for types defined in this crate.
//!
//! Each impl enumerates the type's GC-bearing fields and either calls
//! `field.trace(m)` (delegating to the field's own `Trace` impl) or
//! `m.mark(field)` (when the field is a `Gc<T>` from `lua-gc`). During the
//! Phase A/B/C/D-0 window `GcRef<T>` is still an `Rc<T>` newtype rather
//! than the real `Gc<T>`, so the mark-queue path is not yet reachable —
//! method resolution dispatches through `Deref` to each underlying type's
//! own `trace` method.
use ;
use crateGcRef;
use crateLuaValue;
use crateLuaTable;
use crate;
use crateLuaString;
use crateLuaProto;
use crate;
use crateLuaUserData;
use crateLuaThread;
/// Forwarder for `GcRef<T>`. Now that `GcRef` wraps a real `lua_gc::Gc<T>`
/// (D-1e), tracing must enqueue the box onto the gray queue via
/// `Marker::mark` — that is what flips its header color from White to Gray
/// and ultimately to Black during gray-queue drainage. The previous
/// `try_visit` short-circuit was a Phase A-D-0 workaround for the
/// `Rc`-backed handle (no header, no color), and produced a silent bug
/// post-D-1e: every GC-tracked allocation stayed White and was freed in
/// the sweep on the first `collectgarbage()`. Cycles are now handled
/// natively by the heap's gray-queue (Color::Gray check in `mark` makes
/// re-visits idempotent).
/// LuaValue — central enum. Variants Nil/Bool/Int/Float/LightUserData carry
/// no GC; Str/Table/Function/UserData/Thread carry collectable payloads.
/// LuaString — interned byte string. The `Rc<[u8]>` backing buffer is
/// owned, not GC-managed, so this impl is intentionally empty.
/// UpVal — Open (refers to a thread stack slot by index) or Closed (owns a
/// LuaValue). The Open variant carries no direct GC reference; the slot it
/// points at is traced through the owning thread's stack walk.
/// LuaTable — array+hash entries plus optional metatable.
///
/// Weak-table semantics (matches `lgc.c::traversetable`):
/// * `__mode = "v"` — strong keys, weak values. Trace keys here; value
/// side is deferred — string values get marked in `prune_weak_dead`'s
/// surviving-entry pass (Lua's `iscleared`), non-string dead values
/// trigger entry removal.
/// * `__mode = "kv"` — both sides weak. Trace NEITHER here; everything
/// is handled by `prune_weak_dead` (matches Lua's "just add to allweak,
/// traverse nothing" path).
/// * `__mode = "k"` — weak keys, strong values. Trace NEITHER here. The
/// post-mark ephemeron convergence pass walks each weak-key table's
/// entries and marks values only for entries whose keys are
/// independently reachable. String keys get marked in `prune_weak_dead`.
/// * No `__mode` — trace both unconditionally.
///
/// Marking strings inline for weak slots (the previous behavior) would
/// pin them alive even when their containing entry is about to be cleared
/// because the other side died — breaking the `gc.lua` weak-string-key
/// block, which expects unreferenced long strings to free their bytes
/// after a single `collectgarbage()` cycle.
/// LuaProto — bytecode prototype. k (constants), p (child protos),
/// source, upvalue names, locvar names.
/// LuaLClosure — Lua closure carrying a Proto and its captured upvalues.
/// LuaClosure — dispatch to Lua/C variants; LightC is a bare function-ptr
/// index with no payload.
/// LuaCClosure — Rust-side C closure carrying captured upvalues.
/// LuaUserData — boxed payload + optional metatable + user values.
/// LuaThread — value-side thread identity. Carries only a `ThreadId`
/// (the registry key); the real per-thread `LuaState` lives in
/// `lua-vm`'s `GlobalState::threads` map and is traced from
/// `GlobalState::trace` as a root.
// ──────────────────────────────────────────────────────────────────────────────
// PORT STATUS
// source: n/a (GC Trace impls scoped to lua-types public surface)
// target_crate: lua-types
// confidence: high
// todos: 0
// port_notes: 0
// unsafe_blocks: 0
// notes: Trace impls for GC visitor over the canonical type set. No C analogue;
// the C GC walks struct fields directly via macros.
// ──────────────────────────────────────────────────────────────────────────────