export const description = `Validation tests for implicit conversions and overload resolution`;import { makeTestGroup } from '../../../../common/framework/test_group.js';import { keysOf, objectsToRecord } from '../../../../common/util/data_tables.js';import {kAllNumericScalarsAndVectors,isConvertible,VectorType,} from '../../../util/conversion.js';import { ShaderValidationTest } from '../shader_validation_test.js';export const g = makeTestGroup(ShaderValidationTest);interface Case {expr: string;valid: boolean;f16?: boolean;}const kImplicitConversionCases: Record<string, Case> = {absint_to_bool: {expr: `any(1)`,valid: false,},absint_to_u32: {expr: `1 == 1u`,valid: true,},absint_to_i32: {expr: `1 == 1i`,valid: true,},absint_to_f32: {expr: `1 == 1f`,valid: true,},absint_to_f16: {expr: `1 == 1h`,valid: true,f16: true,},absfloat_to_bool: {expr: `any(1.0)`,valid: false,},absfloat_to_u32: {expr: `1.0 == 1u`,valid: false,},absfloat_to_i32: {expr: `1.0 == 1i`,valid: false,},absfloat_to_f32: {expr: `1.0 == 1f`,valid: true,},absfloat_to_f16: {expr: `1.0 == 1h`,valid: true,f16: true,},vector_absint_to_bool: {expr: `any(vec2(1))`,valid: false,},vector_absint_to_u32: {expr: `all(vec2(1) == vec2u(1u))`,valid: true,},vector_absint_to_i32: {expr: `all(vec3(1) == vec3i(1i))`,valid: true,},vector_absint_to_f32: {expr: `all(vec4(1) == vec4f(1f))`,valid: true,},vector_absint_to_f16: {expr: `all(vec2(1) == vec2h(1h))`,valid: true,f16: true,},vector_absfloat_to_bool: {expr: `any(vec2(1.0))`,valid: false,},vector_absfloat_to_u32: {expr: `all(vec2(1.0) == vec2u(1u))`,valid: false,},vector_absfloat_to_i32: {expr: `all(vec3(1.0) == vec2i(1i))`,valid: false,},vector_absfloat_to_f32: {expr: `all(vec4(1.0) == vec4f(1f))`,valid: true,},vector_absfloat_to_f16: {expr: `all(vec2(1.0) == vec2h(1h))`,valid: true,f16: true,},vector_swizzle_integer: {expr: `vec2(1).x == 1i`,valid: true,},vector_swizzle_float: {expr: `vec2(1).y == 1f`,valid: true,},vector_default_ctor_integer: {expr: `all(vec3().xy == vec2i())`,valid: true,},vector_default_ctor_abstract: {expr: `all(vec3().xy == vec2())`,valid: true,},vector_swizzle_abstract: {expr: `vec4(1f).x == 1`,valid: true,},vector_abstract_to_integer: {expr: `all(vec4(1) == vec4i(1))`,valid: true,},vector_wrong_result_i32: {expr: `vec2(1,2f).x == 1i`,valid: false,},vector_wrong_result_f32: {expr: `vec2(1,2i).y == 2f`,valid: false,},vector_wrong_result_splat: {expr: `vec2(1.0).x == 1i`,valid: false,},array_absint_to_bool: {expr: `any(array(1)[0])`,valid: false,},array_absint_to_u32: {expr: `array(1)[0] == array<u32,1>(1u)[0]`,valid: true,},array_absint_to_i32: {expr: `array(1)[0] == array<i32,1>(1i)[0]`,valid: true,},array_absint_to_f32: {expr: `array(1)[0] == array<f32,1>(1f)[0]`,valid: true,},array_absint_to_f16: {expr: `array(1)[0] == array<f16,1>(1h)[0]`,valid: true,f16: true,},array_absfloat_to_bool: {expr: `any(array(1.0)[0])`,valid: false,},array_absfloat_to_u32: {expr: `array(1.0)[0] == array<u32,1>(1u)[0]`,valid: false,},array_absfloat_to_i32: {expr: `array(1.0)[0] == array<i32,1>(1i)[0]`,valid: false,},array_absfloat_to_f32: {expr: `array(1.0)[0] == array<f32,1>(1f)[0]`,valid: true,},array_absfloat_to_f16: {expr: `array(1.0)[0] == array<f16,1>(1h)[0]`,valid: true,f16: true,},mat2x2_index_absint: {expr: `all(mat2x2(1,2,3,4)[0] == vec2(1,2))`,valid: true,},mat2x2_index_absfloat: {expr: `all(mat2x2(1,2,3,4)[1] == vec2(3.0,4.0))`,valid: true,},mat2x2_index_float: {expr: `all(mat2x2(0,0,0,0)[1] == vec2f())`,valid: true,},mat2x2_wrong_result: {expr: `all(mat2x2(0f,0,0,0)[0] == vec2h())`,valid: false,f16: true,},};g.test('implicit_conversions').desc('Test implicit conversions').params(u => u.combine('case', keysOf(kImplicitConversionCases))).fn(t => {const testcase = kImplicitConversionCases[t.params.case];const code = `${testcase.f16 ? 'enable f16;' : ''}const_assert ${testcase.expr};`;t.expectCompileResult(testcase.valid, code);});const kTypes = objectsToRecord(kAllNumericScalarsAndVectors);const kTypeKeys = keysOf(kTypes);g.test('overload_resolution').desc('Test overload resolution').params(u =>u.combine('arg1', kTypeKeys).combine('arg2', kTypeKeys).beginSubcases().combine('op', ['min', 'max'] as const).filter(t => {if (t.arg1 === t.arg2) {return false;}const t1 = kTypes[t.arg1];const t2 = kTypes[t.arg2];const t1IsVector = t1 instanceof VectorType;const t2IsVector = t2 instanceof VectorType;if (t1IsVector !== t2IsVector) {return false;}if (t1IsVector && t2IsVector && t1.size !== t2.size) {return false;}return true;})).fn(t => {const t1 = kTypes[t.params.arg1];const t2 = kTypes[t.params.arg2];const resTy = isConvertible(t1, t2) ? t2 : t1;const enable = `${t1.requiresF16() || t2.requiresF16() ? 'enable f16;' : ''}`;const min = 50;const max = 100;const res = t.params.op === 'min' ? min : max;const v1 = t1.create(min).wgsl();const v2 = t2.create(max).wgsl();const resV = resTy.create(res).wgsl();const expr = `${t.params.op}(${v1}, ${v2}) == ${resV}`;const assertExpr = t1 instanceof VectorType ? `all(${expr})` : expr;const code = `${enable}const_assert ${assertExpr};`;t.expectCompileResult(isConvertible(t1, t2) || isConvertible(t2, t1), code);});