[naga] Disallow logical operators && and || on vectors

Fixes #6856
This commit is contained in:
Andy Leiserson 2025-03-18 16:08:15 -07:00 committed by Jim Blandy
parent 14690470bb
commit d223bb582f
4 changed files with 65 additions and 5 deletions

View File

@ -283,6 +283,7 @@ By @syl20bnr in [#7326](https://github.com/gfx-rs/wgpu/pull/7326).
- Allows override-sized arrays to resolve to the same size without causing the type arena to panic. By @KentSlaney in [#7082](https://github.com/gfx-rs/wgpu/pull/7082).
- Allow abstract types to be used for WGSL switch statement selector and case selector expressions. By @jamienicol in [#7250](https://github.com/gfx-rs/wgpu/pull/7250).
- Apply automatic conversions to `let` declarations, and accept `vecN()` as a constructor for vectors (in any context). By @andyleiserson in [#7367](https://github.com/gfx-rs/wgpu/pull/7367).
- The `&&` and `||` operators are no longer allowed on vectors. By @andyleiserson in [#7368](https://github.com/gfx-rs/wgpu/pull/7368).
#### General

View File

@ -2261,10 +2261,13 @@ impl<'a> ConstantEvaluator<'a> {
| BinaryOperator::And
| BinaryOperator::ExclusiveOr
| BinaryOperator::InclusiveOr
| BinaryOperator::LogicalAnd
| BinaryOperator::LogicalOr
| BinaryOperator::ShiftLeft
| BinaryOperator::ShiftRight => left_ty,
BinaryOperator::LogicalAnd | BinaryOperator::LogicalOr => {
// Not supported on vectors
return Err(ConstantEvaluatorError::InvalidBinaryOpArgs);
}
};
let components = components

View File

@ -592,9 +592,8 @@ impl<'a> ResolveContext<'a> {
| crate::BinaryOperator::Less
| crate::BinaryOperator::LessEqual
| crate::BinaryOperator::Greater
| crate::BinaryOperator::GreaterEqual
| crate::BinaryOperator::LogicalAnd
| crate::BinaryOperator::LogicalOr => {
| crate::BinaryOperator::GreaterEqual => {
// These accept scalars or vectors.
let scalar = crate::Scalar::BOOL;
let inner = match *past(left)?.inner_with(types) {
Ti::Scalar { .. } => Ti::Scalar(scalar),
@ -607,6 +606,18 @@ impl<'a> ResolveContext<'a> {
};
TypeResolution::Value(inner)
}
crate::BinaryOperator::LogicalAnd | crate::BinaryOperator::LogicalOr => {
// These accept scalars only.
let bool = Ti::Scalar(crate::Scalar::BOOL);
let ty = past(left)?.inner_with(types);
if *ty == bool {
TypeResolution::Value(bool)
} else {
return Err(ResolveError::IncompatibleOperands(format!(
"{op:?}({ty:?}, _)"
)));
}
}
crate::BinaryOperator::And
| crate::BinaryOperator::ExclusiveOr
| crate::BinaryOperator::InclusiveOr

View File

@ -3155,6 +3155,51 @@ fn matrix_vector_pointers() {
);
}
#[test]
fn vector_logical_ops() {
// Const context
check(
"const and = vec2(true, false) && vec2(false, false);",
r###"error: Cannot apply the binary op to the arguments
wgsl:1:13
1 const and = vec2(true, false) && vec2(false, false);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ see msg
"###,
);
check(
"const or = vec2(true, false) || vec2(false, false);",
r###"error: Cannot apply the binary op to the arguments
wgsl:1:12
1 const or = vec2(true, false) || vec2(false, false);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ see msg
"###,
);
// Runtime context
check(
"fn foo(a: vec2<bool>, b: vec2<bool>) {
let y = a && b;
}",
r#"error: Incompatible operands: LogicalAnd(Vector { size: Bi, scalar: Scalar { kind: Bool, width: 1 } }, _)
"#,
);
check(
"fn foo(a: vec2<bool>, b: vec2<bool>) {
let y = a || b;
}",
r#"error: Incompatible operands: LogicalOr(Vector { size: Bi, scalar: Scalar { kind: Bool, width: 1 } }, _)
"#,
);
}
#[test]
fn issue7165() {
// Regression test for https://github.com/gfx-rs/wgpu/issues/7165