4444import dev .cel .policy .CelCompiledRule .CelCompiledMatch .Result ;
4545import dev .cel .policy .CelCompiledRule .CelCompiledMatch .Result .Kind ;
4646import dev .cel .policy .CelCompiledRule .CelCompiledVariable ;
47+ import dev .cel .policy .CelPolicy .EvaluationSemantic ;
4748import dev .cel .policy .CelPolicy .Import ;
4849import dev .cel .policy .CelPolicy .Match ;
4950import dev .cel .policy .CelPolicy .Variable ;
@@ -240,7 +241,12 @@ private CelCompiledRule compileRuleImpl(
240241
241242 CelCompiledRule compiledRule =
242243 CelCompiledRule .create (
243- rule .id (), rule .ruleId (), variableBuilder .build (), matchBuilder .build (), ruleCel );
244+ rule .id (),
245+ rule .ruleId (),
246+ variableBuilder .build (),
247+ matchBuilder .build (),
248+ ruleCel ,
249+ rule .semantic ());
244250
245251 // Validate that all branches in the policy are reachable
246252 checkUnreachableCode (compiledRule , compilerContext );
@@ -256,7 +262,16 @@ private void checkUnreachableCode(CelCompiledRule compiledRule, CompilerContext
256262 CelCompiledMatch compiledMatch = compiledMatches .get (i );
257263 boolean isTriviallyTrue = compiledMatch .isConditionTriviallyTrue ();
258264
259- if (isTriviallyTrue && !ruleHasOptional && i != matchCount - 1 ) {
265+ // Flag literally false conditions as dead code regardless of semantic
266+ if (isConditionLiterallyFalse (compiledMatch .condition ())) {
267+ compilerContext .addIssue (
268+ compiledMatch .sourceId (), CelIssue .formatError (1 , 0 , "Condition is always false" ));
269+ }
270+
271+ if (compiledRule .semantic () == EvaluationSemantic .FIRST_MATCH
272+ && isTriviallyTrue
273+ && !ruleHasOptional
274+ && i != matchCount - 1 ) {
260275 if (compiledMatch .result ().kind ().equals (Kind .OUTPUT )) {
261276 compilerContext .addIssue (
262277 compiledMatch .sourceId (),
@@ -270,6 +285,12 @@ private void checkUnreachableCode(CelCompiledRule compiledRule, CompilerContext
270285 }
271286 }
272287
288+ private static boolean isConditionLiterallyFalse (CelAbstractSyntaxTree condition ) {
289+ CelExpr celExpr = condition .getExpr ();
290+ return celExpr .constantOrDefault ().getKind ().equals (CelConstant .Kind .BOOLEAN_VALUE )
291+ && !celExpr .constant ().booleanValue ();
292+ }
293+
273294 private static CelAbstractSyntaxTree newErrorAst () {
274295 return CelAbstractSyntaxTree .newParsedAst (
275296 CelExpr .ofConstant (0 , CelConstant .ofValue ("*error*" )), CelSource .newBuilder ().build ());
0 commit comments