{"record":{"id":"da867c49744f19f7","repo":"stride3d/stride","slug":"foreach-array-type-is-expected","errorCode":null,"errorMessage":"foreach: Array type is expected","messagePattern":"foreach: Array type is expected","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Statements.Flow.cs","lineNumber":68,"sourceCode":"        builder.Insert(new OpBranch(escapeBlocks.ContinueBlock));\n    }\n}\n\n\npublic partial class ForEach(TypeName typename, Identifier variable, Expression collection, Statement body, TextLocation info) : Loop(info)\n{\n    public TypeName TypeName { get; set; } = typename;\n    public Identifier Variable { get; set; } = variable;\n    public Expression Collection { get; set; } = collection;\n    public Statement Body { get; set; } = body;\n\n    public SymbolFrame? SymbolFrame { get; set; }\n\n    public override void ProcessSymbol(SymbolTable table)\n    {\n        Collection.ProcessSymbol(table);\n        if (!(Collection.Type is PointerType p && p.BaseType is ArrayType arrayType))\n            throw new InvalidOperationException(\"foreach: Array type is expected\");\n\n\n        var variableType = new PointerType(arrayType.BaseType, Specification.StorageClass.Function);\n        Variable.Type = variableType;\n\n        if (TypeName.Name != \"var\")\n            TypeName.ProcessSymbol(table, variableType);\n        else\n            TypeName.Type = arrayType.BaseType;\n\n        // TODO: check conversions\n        if (variableType.BaseType != TypeName.Type)\n            throw new InvalidOperationException(\"foreach: collection and variable type not matching\");\n\n        table.Push();\n        var variableSymbol = new Symbol(new(Variable.Name, SymbolKind.Variable), Variable.Type, 0, OwnerType: table.CurrentShader);\n        table.CurrentFrame.Add(Variable.Name, variableSymbol);\n        Body.ProcessSymbol(table);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Statements.Flow.cs#L50-L86","documentation":"During symbol processing of a foreach statement, the collection expression's resolved type must be a PointerType whose base is an ArrayType (i.e. iterate over a pointer-to-array). Anything else (scalar, struct, non-array pointer) throws this InvalidOperationException, because foreach expansion in SDSL only supports arrays.","triggerScenarios":"foreach over a non-array collection, e.g. a plain struct, a scalar, or a variable whose type failed to resolve to a pointer-to-array during symbol processing.","commonSituations":"Porting C#-style foreach loops over lists to SDSL; typos where the collection variable is a single element; forgetting to declare the collection as an array or to take its pointer.","solutions":["Declare the collection as an array (or a pointer to an array) and pass that to foreach.","Check the collection variable's declared type resolves correctly — fix upstream type errors that leave Collection.Type null or wrong.","Rewrite the loop as an explicit for loop with an index if iterating a non-array."],"exampleFix":"// before\nforeach (var v in singleValue) { ... }\n// after\nfloat values[4];\nforeach (var v in values) { ... }","handlingStrategy":"type-guard","validationCode":"if (collection.Type is not PointerType { BaseType: ArrayType })\n    throw new InvalidOperationException(\"foreach requires a pointer-to-array collection\");","typeGuard":"bool IsForEachable(SymbolType? t) => t is PointerType { BaseType: ArrayType };","tryCatchPattern":"try { foreachStmt.ProcessSymbol(table); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"foreach\")) { reportDiagnostic(foreachStmt.Info, ex.Message); }","preventionTips":["Only use foreach over declared arrays in SDSL.","Run the type checker on the collection expression before the loop.","Use explicit indexed for loops for non-array collections."],"tags":["shader-parsing","sdsl","foreach","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}