Skip to content

Conversation

@joshlf
Copy link
Member

@joshlf joshlf commented Feb 4, 2026


⬇️ Download this PR

Branch

git fetch origin refs/heads/Gb76183f21575d7d2bd0229e4b027d491dae4f5c2 && git checkout -b pr-Gb76183f21575d7d2bd0229e4b027d491dae4f5c2 FETCH_HEAD

Checkout

git fetch origin refs/heads/Gb76183f21575d7d2bd0229e4b027d491dae4f5c2 && git checkout FETCH_HEAD

Cherry Pick

git fetch origin refs/heads/Gb76183f21575d7d2bd0229e4b027d491dae4f5c2 && git cherry-pick FETCH_HEAD

Pull

git pull origin refs/heads/Gb76183f21575d7d2bd0229e4b027d491dae4f5c2

Stacked PRs enabled by GHerrit.

gherrit-pr-id: Gb76183f21575d7d2bd0229e4b027d491dae4f5c2
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @joshlf, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on a series of cleanup and enhancement tasks across the Hermes verification tool. The changes aim to improve the internal architecture, particularly how Rust code is parsed and translated into Lean specifications, and to enhance the user experience through clearer CLI documentation and more robust module handling. Key improvements include a more structured approach to parsing Lean directives, better tracking of module paths for accurate Lean generation, and the introduction of 'verification roots' for selective analysis. The overall impact is a more maintainable, understandable, and powerful verification pipeline.

Highlights

  • Refactored Lean Specification Parsing: The desugar_spec function has been significantly rewritten for clearer and more robust parsing of Lean specifications, explicitly supporting requires, ensures, and forall clauses, and integrating logic previously handled by separate helper functions.
  • Enhanced Module Path Tracking: Implemented comprehensive module path tracking within the SpecVisitor to correctly identify fully qualified names of functions and structs, which is crucial for generating accurate Lean module structures and enabling selective verification.
  • Introduced Verification Roots: A new concept of 'verification roots' (///@ hermes root) has been added, allowing users to specify which functions Charon should start its analysis from, thereby enabling more targeted and efficient verification.
  • Improved CLI and Documentation: The cargo-hermes verify command's CLI arguments now have more detailed descriptions, and overall crate-level and module-level documentation has been expanded for better clarity on Hermes's architecture and pipeline steps.
  • Refined Generic and Trait Translation: The translate_generics function has been enhanced to handle various Rust generic parameters (type, const, lifetime) more robustly, automatically injecting Verifiable constraints and other trait bounds into the generated Lean code.
  • Refactored Integration Tests: The integration test suite has been refactored to use WalkDir for flexible test discovery and now supports filtering test cases via the HERMES_FILTER environment variable, improving developer workflow.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • tools/hermes/src/desugar.rs
    • Rewrote the desugar_spec function to use a more robust line-by-line parsing approach for Lean specifications.
    • Introduced strip_keyword helper for flexible keyword parsing.
    • Explicitly handles requires, ensures, and forall clauses.
    • Updated DesugaredSpec struct with better field documentation and reordered fields.
    • Removed the generate_body and parse_binders helper functions, integrating their logic into desugar_spec.
    • Added new unit tests for simple requires/ensures and forall cases.
    • Added license header.
  • tools/hermes/src/docs.rs
    • Added Javadoc-style comments and examples to parse_hermes_tag.
    • Clarified the purpose of is_hermes_directive and iter_hermes_lines.
    • Added an empty line for better formatting in parse_doc_attr's doc comment.
  • tools/hermes/src/include/Std.lean
    • Changed def ConstPtr to abbrev ConstPtr in Std.lean.
  • tools/hermes/src/lib.rs
    • Rewrote the main crate documentation to provide a high-level overview of Hermes's purpose and pipeline.
    • Added module-level documentation for desugar, docs, orchestration, parser, pipeline, shadow, and translator modules.
  • tools/hermes/src/main.rs
    • Added detailed documentation to the HermesArgs struct and Commands::Verify fields.
    • Clarified the purpose of crate_name, dest, aeneas_path, manifest_path, and allow_sorry arguments.
  • tools/hermes/src/orchestration.rs
    • Added start_from: &[String] parameter to run_charon function.
    • Updated run_charon documentation to reflect the new start_from argument and clarify existing parameters.
    • Added cmd.arg("--start-from") logic to Charon invocation.
  • tools/hermes/src/parser.rs
    • Added path: Vec<String> to ParsedFunction and ParsedStruct to store module hierarchy.
    • Modified SpecVisitor to track current_path for module scope.
    • Updated visit_item_fn and visit_item_struct to populate the path field.
    • Improved visit_item_struct to correctly parse multi-line lean invariant blocks and strip is_valid self := prefixes.
    • Changed extract_blocks to return the first error encountered instead of concatenating all.
    • Added documentation to ParsedFunction, ParsedStruct, ExtractedBlocks, SpecVisitor, and extract_blocks.
  • tools/hermes/src/pipeline.rs
    • Updated get_crate_name to handle single-file scripts more robustly.
    • Added Javadoc-style comments to get_crate_name, Sorry enum, run_pipeline, stitch_user_proofs, generate_lean_file, and write_lakefile.
    • Modified run_pipeline to pass is_script_mode to stitch_user_proofs.
    • Refactored stitch_user_proofs to calculate file-based module paths (src/foo/bar.rs -> foo::bar) and prepend them to ParsedFunction and ParsedStruct paths.
    • Implemented namespace opening/closing in generate_lean_file for UserProofs.lean and FunsExternal.lean based on func.path.
    • Refined the generation of noncomputable def for model functions in FunsExternal.lean, using Classical.choose and handling exists clauses.
    • Clarified imports for FunsExternal.lean to explicitly import Types.
    • Added Verifiable instance generation for structs, including generic parameter handling.
    • Improved argument validity checks in UserProofs.lean generation.
    • Added step-by-step comments to run_pipeline (Step 1: Shadow Crate, Step 2: Charon, etc.).
    • Added sorry_mode documentation.
  • tools/hermes/src/shadow.rs
    • Modified create_shadow_crate to return Vec<String> for roots in addition to models.
    • Updated sanitize_crate to also return roots.
    • Introduced is_root flag in parse_model_specs and ShadowVisitor to identify functions marked with any Hermes attribute as verification roots.
    • Added roots collection to ShadowVisitor and process_file_content.
    • Updated inject_prelude with detailed comments explaining its purpose and mechanism.
    • Added documentation to create_shadow_crate, inject_prelude, process_file_content, sanitize_crate, ShadowVisitor.
    • Clarified model substitution logic in ShadowVisitor.
  • tools/hermes/src/translator.rs
    • Rewrote translate_generics to use match for GenericParam types.
    • Automatically adds [Verifiable T] for type parameters.
    • Extracts and adds trait bounds (e.g., [instTDisplay : Display T]) for type parameters.
    • Added basic handling for Const generic parameters.
    • Added Javadoc-style comments to SignatureTranslator and its methods.
  • tools/hermes/tests/integration.rs
    • Replaced run_suite with a single integration_tests function that uses WalkDir to find all .rs files in tests/cases.
    • Implemented HERMES_FILTER environment variable support for selective test execution (e.g., HERMES_FILTER=my_test or HERMES_FILTER=!fail_).
    • Updated setup_env to use AENEAS_PATH environment variable if available.
    • Improved error messages for failed pipeline runs in run_case.
    • Added anyhow and walkdir imports.
Activity
  • This pull request is marked as 'Work In Progress' (WIP), indicating ongoing development.
  • The PR description includes a gerrit-pr-id, suggesting it's part of a larger development workflow, possibly with external review or tracking.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant and valuable cleanup of the Hermes codebase. The refactoring greatly improves code clarity, maintainability, and documentation across multiple modules, especially in desugar.rs, parser.rs, and pipeline.rs. The introduction of features like selective extraction via verification roots (--start-from) and the improved testing infrastructure are excellent additions. The code is now more idiomatic and easier to follow. I've identified a few areas for improvement, including a potential regression in how structs are parsed and some minor code cleanup opportunities.

Comment on lines +223 to 233
let invariant =
if !invariant_lines.is_empty() { Some(invariant_lines.join("\n")) } else { None };

if let Some(inv) = invariant {
self.structs.push(ParsedStruct {
ident: node.ident.clone(),
generics: node.generics.clone(),
invariant,
invariant: Some(inv),
path: self.current_path.clone(),
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This change appears to be a regression. The new logic only collects structs that have an explicit ///@ lean invariant. The previous implementation collected all structs, which is necessary because even structs without a custom invariant may require a default Verifiable instance for proofs involving them to compile. It's recommended to restore the behavior of collecting all structs to avoid potential compilation errors in the generated Lean code.

        if !self.structs.iter().any(|s| s.ident == node.ident && s.path == self.current_path) {
            self.structs.push(ParsedStruct {
                ident: node.ident.clone(),
                generics: node.generics.clone(),
                invariant,
                path: self.current_path.clone(),
            });
        }

// This file may not be copied, modified, or distributed except according to
// those terms.

use anyhow::{Context, Result, anyhow};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Context and anyhow imports are not used in this file and can be removed to keep the imports clean.

Suggested change
use anyhow::{Context, Result, anyhow};
use anyhow::Result;

Comment on lines 172 to 190
if !content.is_empty() {
invariant_lines.push(content.to_string());
}
} else {
match current_mode {
Some("invariant") => {
let content = trimmed[1..].trim();
invariant_lines.push(content.to_string());
}
None => {
self.errors.push(anyhow::anyhow!(
"Found `///@` line without preceding `lean invariant` on struct '{}'",
node.ident
));
}
_ => {}
invariant = Some(content.to_string());
// We assume only one invariant block for now or take the last?
// Or we could join them? Hermes usually expects one block.
// Let's just break after finding one for simplicity or join if multiline logic needed?
// But `iter_hermes_lines` yields *lines*.
// If the user writes:
// ///@ lean invariant
// ///@ x > 0
// ///@ y > 0
// We need to capture subsequent lines.
// The `parse_hermes_tag` only handles match on the SAME line or activation.
}
} else if invariant.is_some() {
// Append continuation lines if we are in invariant mode?
// But `iter_hermes_lines` loop doesn't maintain state easily across iterations if we don't track it.
// We need `current_mode` state tracking like in `visit_item_fn`.
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of code and its associated comments appear to be leftovers from a previous refactoring attempt. The logic here is flawed (as noted in the comments themselves) and is superseded by the correct implementation that follows. This should be removed to avoid confusion for future readers.

funs_external_content.push_str(" Result.ok (Classical.choose h)\n");
}
funs_external_content.push_str(" else\n Result.fail Error.panic\n\n");
funs_external_content.push_str(" else\n Result.fail Error.panic\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better readability in the generated FunsExternal.lean file, consider adding an extra newline after this line. This will visually separate the model definition from the end namespace statements that follow.

Suggested change
funs_external_content.push_str(" else\n Result.fail Error.panic\n");
funs_external_content.push_str(" else\n Result.fail Error.panic\n\n");

@codecov-commenter
Copy link

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.02%. Comparing base (d3ff7ee) to head (33bbb15).

Additional details and impacted files
@@                            Coverage Diff                             @@
##           Gbeca6e8c6a2f4e776c00719d86c9eabf4f63fe2e    #2980   +/-   ##
==========================================================================
  Coverage                                      92.02%   92.02%           
==========================================================================
  Files                                             19       19           
  Lines                                           6029     6029           
==========================================================================
  Hits                                            5548     5548           
  Misses                                           481      481           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants