Conversation
Introduces a new op_table module with a scope-based operation lookup system for dynamic operator dispatch in cel-parser. The parser now supports custom operation scopes, efficient built-in operator tables using phf, and exposes op_lookup_mut for extensibility. Includes new tests and documentation, and updates dependencies to add phf and once_cell.
Enhanced literal parsing in LexLexer to use syn::parse2 for better span preservation and added the 'parsing' feature to the syn dependency. Expanded documentation for parser structures and methods in lib.rs, including detailed doc comments for primary expressions, probe results, error formatting, and parsing entry points. Improved test assertions and error reporting in parser tests.
Refactored conditional logic in cel-parser to use && let chains for improved readability and conciseness. Expanded .vscode/tasks.json with comprehensive build, test, documentation, clippy, and sanitizer tasks for multiple platforms to streamline development workflows.
Added and reorganized tasks in .vscode/tasks.json for improved Rust workflow. Expanded sanitizer support for Linux/WSL2 and Windows, clarified platform-specific notes, and added a comprehensive test task for Windows. This update enhances cross-platform development and testing capabilities.
Updated .vscode/tasks.json to streamline task definitions by changing command types to 'cargo' for clippy and adjusting environment variables for better clarity. Removed experimental Windows tasks to focus on macOS and Linux/WSL2 support, enhancing the overall development experience.
Updated the error handling logic in the expression function to use the is_err() method for improved clarity and conciseness. This change enhances the readability of the parser code.
The lexer (`LexLexer`) no longer returns `Result` and is now infallible, as all input is pre-validated by `proc_macro2`. The parser (`CELParser`) is updated to remove error handling for lexer errors, simplifying token peeking and advancement. Documentation is updated to clarify error handling in both lexer and parser. Macro now only reports errors for non-matching expressions, not parse errors.
Move the CEL parser implementation from the separate cel-parser crate into cel-runtime::parser, remove the cel-parser crate and its example docs, and update workspace/Cargo manifests. CELParser API changed: constructor now takes an OpLookup, tokens are set via set_tokens/parse_tokens/parse_str, postfix/call parsing added, and error/reporting helpers adjusted. Updated lex_lexer to use a concrete TokenStreamIter type and relocated files under cel-runtime/src/parser; cel-rs-macros now depends on cel-runtime and uses CELParser/OpLookup accordingly. Also export parser types and implement FromStr for DynSegment to allow parsing from strings; tests updated to the new API.
Add a .cursor rule encouraging no-heap allocations and implement several refactors to reduce temporaries and allocations. Introduce PunctOp (no-heap punctuation token) and replace String-based punct tokens. Extend StackInfo with Cow<'static, str> type_name, padding flag, dropper, and AssociatedType to record nested types; store argument_names in DynSegment. Replace peek_types_vec with peek_stack_infos(&[StackInfo]) returning a slice to avoid allocating Vec<TypeId>. Change ScopeFn/OpLookup APIs to accept &mut DynSegment and a num_operands so scopes can inspect the stack without extra allocations; update builtin lookup and parser call sites and tests accordingly. Improve error messages to include human-readable type names.
Add a dedicated CELError type (with message and proc_macro2::Span) and a rustc-style formatter, and refactor the parser to return CELError instead of anyhow::Error. Removed the parser's compile_error token-output plumbing and helper extraction/formatting methods; replaced report_error with error_at that constructs CELError at the current span. Updated CEL macro to emit compile_error! using CELError spans and literals. Re-export CELError from runtime, adjusted FromStr and parser APIs/Result type, and updated tests to work with the new error type and formatting.
Introduce a Send+Sync SourceSpan and switch CELError to store it (with helper from_proc_macro2) so parse errors can be used across threads. Adjust proc-macro handling to emit compile_error! at call_site and use SourceSpan defaults. Add fallible operation support: DynSegment.op1r/op2r with stack-unwinding droppers and RawSegment::raw2 helper to run fallible binary ops. Update op_table to use op1r/op2r for checked integer arithmetic and shifts (returning errors on overflow/invalid shifts) and add tests for overflow and unwind behavior.
Drop manual unsafe impl Send/Sync for SourceSpan and CELError in parser/error.rs. Reformat cel-runtime/src/parser/op_table.rs: reorder anyhow import, reflow many long closure expressions across multiple lines for readability, compact some signature arrays onto single lines, and tidy minor test formatting. These are mostly non-functional formatting/import changes; only behavioral change is removal of the explicit unsafe Send/Sync impls.
| "problemMatcher": [ | ||
| "$rustc" | ||
| ] | ||
| }, |
| let mut segment = Segment::new(experiment, |e| e.a.to_string()); | ||
| assert_eq!(segment.call(), "1"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Accidentally committed experimental test code in lib
Low Severity
The tests module in src/lib.rs contains Experiment and Segment structs with a single experiment test that appears to be personal prototyping code unrelated to the PR's parser rework. This test module duplicates the name Segment (which exists as a real type in cel-runtime) and doesn't test any actual library functionality.
Replace standalone matches! calls with assert!(matches!(...)) in cel-runtime/src/parser/lex_lexer.rs tests. The previous matches! usages were no-ops and did not fail the test on mismatch; wrapping them with assert! ensures the tests actually verify token shapes and will fail when tokens differ from expectations.
| sig!(TYPE_ISIZE, 2, |seg| seg.op2r(|a: isize, b: isize| a | ||
| .checked_shl(b as u32) | ||
| .ok_or_else(|| anyhow!("shift overflow")))), | ||
| ]; |
There was a problem hiding this comment.
Unsigned shift operations panic on oversized shift amounts
Medium Severity
Unsigned shift operations in LEFT_SHIFT_SIGNATURES and RIGHT_SHIFT_SIGNATURES (e.g., a: u8 << b: u8) use unchecked << and >> via op2, which panics in debug mode when the shift amount exceeds or equals the bit width. Signed shifts correctly use checked_shl/checked_shr with op2r. Unsigned shifts need the same treatment — either wrapping_shl/wrapping_shr (consistent with wrapping_add for unsigned) or checked_shl/checked_shr with op2r.
Additional Locations (1)
| println!("{}", e.format_rustc_style(source, file!(), line)); | ||
| } | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Experiment test always passes, hiding parse failures
Low Severity
The experiments test has its actual assertion commented out (// assert!(parser.parse_str(source)?.call0::<bool>()?);). It silently catches parse errors via if let Err, prints them, and returns Ok(()) regardless. This test always passes even when the expression fails to parse, giving a false sense of coverage.
| _ => { | ||
| // Future literal types not yet handled | ||
| } | ||
| } |
There was a problem hiding this comment.
Literal parsing panics on out-of-range user input values
High Severity
The push_literal function uses .expect() on every base10_parse call, which panics when a literal value overflows the target type. Since this is called from parse_str (which processes user-provided CEL expressions at runtime), input like "999999999999" (overflows default i32) or "256u8" will cause a runtime panic instead of returning a CELError. All other arithmetic errors in the crate (e.g., overflow in checked_add) return graceful Err values, making this an inconsistent and dangerous panic path from user input.
Use integer checked_div/checked_rem wrapped with op2r for all integer division and modulo signatures so division-by-zero returns an error instead of panicking; float behavior remains unchanged. Add explanatory comments and unit tests (division_by_zero and modulo_by_zero) that assert the error contains "division by zero". This prevents runtime panics and surfaces a clear error to callers.


This pull request makes several improvements to Rust development workflows and code quality standards for the project. The most significant changes include the removal of the
cel-parsercrate, enhancements to documentation and allocation guidelines, expanded VSCode build/test tasks, and updates to dependencies and macro usage to reflect the new crate structure.Project structure and dependencies:
cel-parsercrate from the workspace and dependencies, consolidating parsing functionality intocel-runtime. All references and dependencies oncel-parserhave been eliminated fromCargo.tomlfiles and the workspace configuration. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-2e9d962a08321605940b5a657135052fbcef87b5e360662bb527c96d9a615542L9-R15),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-b9957dc1b6aedbcdeff4fbce5b4221da59ef2dd8884b80c051f4fe6ee3108f8dL1-L12),[[3]](https://github.com/stlab/cel-rs/pull/9/files#diff-3823bfb8141007195f06dc4ffabcc9e2db3fd93d37624332d46e88bcfd20c48bL14-R14))cel-rs-macroscrate to depend oncel-runtimeinstead ofcel-parser, and refactored macro code to use parsing and error types fromcel-runtime. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-3823bfb8141007195f06dc4ffabcc9e2db3fd93d37624332d46e88bcfd20c48bL14-R14),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L33-R36),[[3]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L48-L52))Development tooling:
[.vscode/tasks.jsonR4-R352](https://github.com/stlab/cel-rs/pull/9/files#diff-7d76d7533653c23b753fc7ce638cf64bdb5e419927d276af836d3a03fdf1745aR4-R352))[.vscode/settings.jsonL10-R11](https://github.com/stlab/cel-rs/pull/9/files#diff-a5de3e5871ffcc383a2294845bd3df25d3eeff6c29ad46e3a396577c413bf357L10-R11))Code quality and documentation standards:
[.cursor/rules/avoid-heap-allocations.mdcR1-R87](https://github.com/stlab/cel-rs/pull/9/files#diff-d13685b400c5d4957f64a3d3644543afc23c9f80bff059aa3542cfe5adc431aeR1-R87))[.cursor/rules/doc-comments.mdcL2-R154](https://github.com/stlab/cel-rs/pull/9/files#diff-bc71edfe8cc02c0facfc56fc6371c9bf2d90055cb84af398575c9f3dc2c204ddL2-R154))Dependency updates:
cel-runtime(e.g.,proc-macro2,quote,owo-colors,syn,phf,once_cell) to support the consolidated parsing and macro infrastructure. ([cel-runtime/Cargo.tomlL10-R15](https://github.com/stlab/cel-rs/pull/9/files#diff-b401c530f9e812ac243c304a31f8c72e20f1a285e1fdbd95fdb804581cdd1bf2L10-R15))Macro and parsing improvements:
expressionmacro incel-rs-macrosto use the new parser interface fromcel-runtime, improving error reporting and aligning with the new crate structure. Also updated theprint_tokens!macro documentation example. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L33-R36),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L48-L52),[[3]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L61-R74))Detailed list of changes:
Project structure and dependencies
cel-parsercrate from the workspace and all related dependencies, consolidating parsing functionality intocel-runtime. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-2e9d962a08321605940b5a657135052fbcef87b5e360662bb527c96d9a615542L9-R15),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-b9957dc1b6aedbcdeff4fbce5b4221da59ef2dd8884b80c051f4fe6ee3108f8dL1-L12))cel-rs-macrosto depend oncel-runtimeinstead ofcel-parser, and refactored macro code accordingly. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-3823bfb8141007195f06dc4ffabcc9e2db3fd93d37624332d46e88bcfd20c48bL14-R14),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L33-R36),[[3]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L48-L52))Development tooling
[.vscode/tasks.jsonR4-R352](https://github.com/stlab/cel-rs/pull/9/files#diff-7d76d7533653c23b753fc7ce638cf64bdb5e419927d276af836d3a03fdf1745aR4-R352))[.vscode/settings.jsonL10-R11](https://github.com/stlab/cel-rs/pull/9/files#diff-a5de3e5871ffcc383a2294845bd3df25d3eeff6c29ad46e3a396577c413bf357L10-R11))Code quality and documentation
[.cursor/rules/avoid-heap-allocations.mdcR1-R87](https://github.com/stlab/cel-rs/pull/9/files#diff-d13685b400c5d4957f64a3d3644543afc23c9f80bff059aa3542cfe5adc431aeR1-R87))[.cursor/rules/doc-comments.mdcL2-R154](https://github.com/stlab/cel-rs/pull/9/files#diff-bc71edfe8cc02c0facfc56fc6371c9bf2d90055cb84af398575c9f3dc2c204ddL2-R154))Dependencies
cel-runtimeto support parsing, macro expansion, and colorized output. ([cel-runtime/Cargo.tomlL10-R15](https://github.com/stlab/cel-rs/pull/9/files#diff-b401c530f9e812ac243c304a31f8c72e20f1a285e1fdbd95fdb804581cdd1bf2L10-R15))Macros and parsing
expressionmacro to use the newCELParserinterface fromcel-runtime, improving error handling and reporting. Updated documentation for theprint_tokens!macro. ([[1]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L33-R36),[[2]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L48-L52),[[3]](https://github.com/stlab/cel-rs/pull/9/files#diff-c187b9b22359c2452046a640b14f4e3748f18cc98c62ce1ed00bfc82ca709c20L61-R74))Note
High Risk
Large refactor that replaces a crate and introduces new parsing and operator-dispatch logic while changing runtime stack unwinding behavior, so regressions could affect expression validation/execution and error reporting.
Overview
Consolidates CEL parsing into
cel-runtimeby deleting the standalonecel-parsercrate and introducing a newcel_runtime::parsermodule (lexer, typed operator tableOpLookup, andCELErrorwith rustc-style diagnostics), plus aDynSegment: FromStrentrypoint for parsing strings into executable segments.Extends the runtime execution layer to support fallible unary/binary ops (
op1r/op2r) with correct stack unwinding, improves type metadata (StackInfonow carriestype_nameand exposespeek_stack_infos) for better operation errors, and updatescel-rs-macros::expression!and public re-exports to use the new parser API.Also adds/enforces Cursor rules for doc comments and avoiding heap allocations, expands VSCode tasking (build/test/doc/clippy/sanitizers), and updates
cel-runtimedependencies to support parsing and perfect-hash builtin op dispatch.Written by Cursor Bugbot for commit f56113a. This will update automatically on new commits. Configure here.