{"record":{"id":"dc0d416ddf895c43","repo":"stride3d/stride","slug":"can-t-cast-between-array-of-different-types-cast-from","errorCode":null,"errorMessage":"Can't cast between array of different types (cast from {valueType} to {castType})","messagePattern":"Can't cast between array of different types \\(cast from (.+?) to (.+?)\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs","lineNumber":508,"sourceCode":"        if (castType == valueType)\n            return value;\n\n        if (castType is StructType || valueType is StructType)\n            throw new NotImplementedException($\"Can't cast between structures (cast from {valueType} to {castType})\");\n\n        if (castType is ArrayType a1 && valueType is ArrayType a2)\n        {\n            if (a1.BaseType == a2.BaseType)\n            {\n                if (a1.Size != -1 && a1.Size != a2.Size)\n                    throw new InvalidOperationException(($\"Can't cast between array of different sizes (cast from {valueType} to {castType})\"));\n                // Some sizes are undetermined; this can only happen during compilation due to incomplete generics type\n                // TODO: do a \"check pass\" later to make sure this won't happen after generics instantiation?\n                return value;\n            }\n            else\n            {\n                throw new InvalidOperationException(($\"Can't cast between array of different types (cast from {valueType} to {castType})\"));\n            }\n        }\n\n        if (castType is StreamsType { Kind: var targetKind }\n            && valueType is StreamsType { Kind: var sourceKind }\n            // Note: order is Input, Streams, Output\n            && targetKind > sourceKind)\n        {\n            return new(InsertData(new OpCopyLogical(context.GetOrRegister(castType), context.Bound++, value.Id)));\n        }\n\n        // We don't support cast with object yet, filter for numeral types\n        if ((castType is not ScalarType && castType is not VectorType && castType is not MatrixType)\n            || (valueType is not ScalarType && valueType is not VectorType && valueType is not MatrixType))\n            throw new NotImplementedException($\"Cast only work between numeral types (cast from {valueType} to {castType})\");\n\n        // One entry per column of the SPIR-V matrix (i.e. per HLSL row), since MatrixType.Columns\n        // is the OpTypeMatrix column count and MatrixType.Rows the size of each column vector.","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs#L490-L526","documentation":"When converting between array types whose base element types differ (e.g. int[] to float[]), Convert has no per-element lowering and throws InvalidOperationException. Array casts are only permitted when base types are identical (and sizes match).","triggerScenarios":"Calling Convert where both types are ArrayType but a1.BaseType != a2.BaseType.","commonSituations":"Casting an int array to a float array in shader code; texture offset/coordinate helpers receiving arrays of the wrong element type; API changes that altered array element type without updating callers.","solutions":["Convert the array element-by-element into a new array of the target element type","Change the source array to the target element type at construction","Loosen the receiving API to accept the source element type","Add element-wise conversion support to Convert if this cast should be legal"],"exampleFix":"// before\nfloat[] f = (float[])intArray; // different element types\n// after\nvar f = new float[intArray.Length];\nfor (int i = 0; i < intArray.Length; i++) f[i] = (float)intArray[i];","handlingStrategy":"type-guard","validationCode":"if (valueType is ArrayType s && castType is ArrayType d && s.BaseType != d.BaseType)\n    throw new InvalidOperationException(\"Convert array elements explicitly before casting\");","typeGuard":"bool ArrayBaseTypesMatch(ArrayType a, ArrayType b) => a.BaseType == b.BaseType;","tryCatchPattern":"try { converted = Builder.Convert(value, castType); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"array of different types\"))\n{ /* convert per-element into a new array instead */ }","preventionTips":["Use a single element type across array pipelines","Convert elements individually when element type must change","Avoid int[]/float[] cross-casts in shader code"],"tags":["spirv","shader-compiler","array","casting"],"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"}