More info on __gc and __mode

Metatables

__gc doesn’t mention that it only works with userdatas (in 5.1), and that it’s disabled in roblox and will never fire.

__mode doesn’t give enough information about the behavior with instances.

Instances can be weak, as they are userdatas, and userdatas work with weak tables.

local weak = setmetatable({},{__mode="v"})
weak[1] = Instance.new"Folder"
wait(2)
print(weak[1])
--> nil

It is also wrong saying that tables that hold instance references will never be garbage collected.

local weakvals = {__mode="v"}
local weak = setmetatable({},weakvals)
weak[1] = setmetatable({},weakvals)
weak[1][1] = workspace -- won't be collected, as it's a global
wait(2)
print(weak[1])
--> nil

It should mention how an instance being under DataModel doesn’t prevent it being removed from the weak table. Having an instance with a property pointing to that instance being held in the weak table also doesn’t prevent it from being removed from the weak table. (e.g ObjectValue, or just any object parented to it)

For instance,
local weak = setmetatable({},{__mode="v"})
weak[1] = workspace.Terrain
wait(2)
print(weak[1])
--> nil
print(workspace.Terrain)
--> Terrain

However adding a strong reference makes the terrain instance stay in the weak table.

local weak = setmetatable({},{__mode="v"})
weak[workspace.Terrain] = 1
weak[1] = workspace.Terrain
wait(2)
print(weak[1])
--> Terrain
print(workspace.Terrain)
--> Terrain

Weird behavior, but I think it should be documented better.

The documentation should also mention what __mode should be.
“v” = weak values
“k” = weak keys
“kv” or “vk” = weak keys and weak values

The documentation doesn’t state what weak references are, which it probably should.

21 Likes

Arguably, __gc shouldn’t even be documented on the developer hub since it’s of no use to developers. It would be like documenting the io library from vanilla Lua.

2 Likes

Bumping since this is not fixed. Was literally just discussing this and it is incorrect that references to Roblox instances aren’t weak.

The code I used was the same as the one in the OP.

1 Like

Bump. This behavior is still documented incorrectly.

Bumping again because I got caught out by this recently thinking an instance reference would only be treat weak once it was destroyed.

Trust me I’m a bad programmer sometimes.

Bada-bing, bada-bump. Somebody please fix this.

2 Likes