Skip to content

Luau: read/write modifier in array types merges into the element type, changing code meaning ({ read Foo } -> { readFoo }) #1126

Description

@Tycoonomics

Affects StyLua 2.5.2 (latest release); the relevant code is unchanged on current main. Found while adopting solver-V2 read syntax in a Roblox project.

Repro

Input:

type A = { read Service }
type B = { write Service }

Output (default config):

type A = { readService }
type B = { writeService }

The space after the access modifier is dropped, merging the two tokens into a single type reference readService — the output parses but means something different (and typically breaks analysis with an unknown-type error). --verify correctly refuses to write:

INTERNAL WARNING: Output AST may be different to input AST. Code correctness may have changed.

The equivalent property and indexer positions are unaffected: { read Name: string } and { read [number]: Service } both format correctly (the latter is a working workaround for the array shorthand).

Multiline variant

The multiline path misplaces indentation as well — the element type's leading indent lands between the modifier and the type, and the modifier gets no indent:

-- input
type C = {
	-- keep
	read Service
}
-- output
type C = {
-- keep
read	Service
}

Likely cause

In src/formatters/luau.rs, the TypeInfo::Array arm formats the access token with format_token_reference only, never re-appending trailing trivia. The sibling TypeField access handling in format_type_field appends an explicit space:

.update_trailing_trivia(FormatTriviaType::Append(vec![Token::new(
    TokenType::spaces(1),
)]))

(access_shape_increment in the Array arm already budgets len() + 1 for that space — it just isn't emitted.) For the multiline case, the leading indent trivia is attached to type_info even when an access token precedes it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions