Summary:
OLS fails to infer the correct expected type for a struct literal's fields when that literal is an argument to a function call, and that call itself is an element of another array/composite literal (e.g. a []T{ f({...}) } shape). Instead of completing against the argument's actual parameter type, OLS falls back to suggesting field names from an unrelated/outer scope. This only affects editor completion — the code compiles and runs correctly with odin build/odin check.
Minimal Repro:
package main
Inner :: struct {
top: u16,
color: [4]f32,
}
Config :: struct {
borders: Inner,
}
make_thing :: proc(config: Config) -> int {
return 0
}
main :: proc() {
_ = []int{
make_thing({borders = {}}), // <- cursor after "borders = ", trigger completion
// Expected: completion offers Inner's fields (top, color)
// Actual: completion offers unrelated/outer-scope suggestions
}
}
Steps to reproduce:
- Open the file above (or an equivalent) in an editor with OLS attached.
- Place the cursor immediately after borders = inside the nested make_thing({...}) call.
- Trigger completion (Ctrl+Space).
Expected: Completion suggests Inner's fields (top,color).
Actual: Completion suggests incorrect/unrelated fields names, (actually grabs the intellisense that should be called if it would done on the outer scope) as if it lost track of the expected type at that position.
Additional Notes:
- The same call written as a top-level, non-nested statement (
make_thing({borders = {}}) outside any enclosing array/composite literal) completes correctly.
- The issue reproduces regardless of whether the enclosing struct types are unions, plain structs, recursive, or reference external-package types — it appears specifically tied to the call being an element of a composite literal, not to any particular type shape.
- Naming the inner literal explicitly (
borders = Inner{...}) works around the issue, since it removes the need for inference.
- Wrapping the nested call in an
if-gated block (rather than a composite literal) also avoids the issue, since the block's scope ownership becomes grammatically unambiguous.
I'm building a gui framework with a declarative builder-style api and this issue breaks the expected dev experience of reliable field completions when nesting components.
Environment: ols version nightly-2026-09-06-8a347aa8, ols version nightly-2026-09-06-8a347aa8, vscode 1.131.0, OS - Linux
Summary:
OLS fails to infer the correct expected type for a struct literal's fields when that literal is an argument to a function call, and that call itself is an element of another array/composite literal (e.g. a
[]T{ f({...}) }shape). Instead of completing against the argument's actual parameter type, OLS falls back to suggesting field names from an unrelated/outer scope. This only affects editor completion — the code compiles and runs correctly withodin build/odin check.Minimal Repro:
Steps to reproduce:
Expected: Completion suggests
Inner's fields (top,color).Actual: Completion suggests incorrect/unrelated fields names, (actually grabs the intellisense that should be called if it would done on the outer scope) as if it lost track of the expected type at that position.
Additional Notes:
make_thing({borders = {}})outside any enclosing array/composite literal) completes correctly.borders = Inner{...}) works around the issue, since it removes the need for inference.if-gated block (rather than a composite literal) also avoids the issue, since the block's scope ownership becomes grammatically unambiguous.I'm building a gui framework with a declarative builder-style api and this issue breaks the expected dev experience of reliable field completions when nesting components.
Environment:
ols version nightly-2026-09-06-8a347aa8,ols version nightly-2026-09-06-8a347aa8,vscode 1.131.0,OS - Linux