lloyAlloy on GitHub
ParallelError
Docs

ParallelError

Updated

The rule behind this error is on the Parallel Luau page.

local parts: { BasePart } = {}
local hits: { BasePart } = {}

parallel do
    for _, part in parts do
        if part.Position.Y < 0 then
            table.insert(hits, part)
        end
    end
end

for _, part in hits do
    part.Position = new Vector3(0, 10, 0)
end

Runs the block in the parallel phase. The engine runs code in parallel only in a script under an Actor, so the block goes in a .server.actor.aly or .client.actor.aly script, or in a module that such a script requires. alloy doc actor has the infix.

The emit writes task.desynchronize() do on the line of the header and task.synchronize() end on the line of the end. The line count holds, and the block keeps its own scope. The block is a statement and not an expression, because the phase belongs to the thread and not to a value.

The compiler refuses what the engine refuses, as far as this file shows it:

  • a write to Parent, and a write to a property of an Instance that the file knows;
  • Instance.new, new Instance, Destroy and Clone with a colon or a dot, destroy, and delete;
  • a call to a function or a struct method of this file that does one of those, at any depth;
  • a parallel block inside the block;
  • await, because a Future resumes in the serial phase;
  • a return, a break, or a continue that leaves the block, because the thread would skip task.synchronize().

The file knows an Instance by:

  • an annotation or a cast with an Instance class;
  • a Roblox global, such as workspace, and the fields under it;
  • Instance.new, GetService, FindFirstChild, WaitForChild, Clone, ->, or =>;
  • an element of a table typed { T } or { [K]: T } of an Instance class, by index or in a loop;
  • a struct field with an Instance class;
  • a parameter of an as parallel handler, typed by its message.

A name that the block binds hides an outer name with the same spelling.

Each report names the rule, and the write it refuses: a parallel block cannot write part.Position; move the write after the block. The quick fix moves a refused statement after the block when nothing later in the block reads what it writes.

This check is a guard rail, not a proof. It reads this file and no further. A call into another module is not followed. A write through a value typed any, or through a table the file does not type, cannot be seen. The engine has the last word, and its error comes at run time.

SharedTable is the Roblox type for state that several actors share. Alloy does not wrap it, and a message carries one like any other value.

The word is free as a name. parallel opens the block only before do on the same line, so local parallel = true and parallel(x) read the Luau way.