-
Notifications
You must be signed in to change notification settings - Fork 4
Phased and Confused: typestate enforcement for post-mono Body invariants #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,8 +9,9 @@ | |||||||||||||||||||||||||||||||||
| //! | Module | Responsibility | | ||||||||||||||||||||||||||||||||||
| //! |--------|----------------| | ||||||||||||||||||||||||||||||||||
| //! | [`schema`] | Data model types ([`SmirJson`], [`Item`], [`AllocInfo`], etc.) and type aliases; [`Item`] deliberately excludes `MonoItem` for structural phase separation | | ||||||||||||||||||||||||||||||||||
| //! | [`collect`] | Three-phase pipeline: collect items, analyze bodies, assemble final output; phase boundary is enforced structurally via the `(MonoItem, Item)` split | | ||||||||||||||||||||||||||||||||||
| //! | [`items`] | Constructing `(MonoItem, Item)` pairs and extracting debug-level details | | ||||||||||||||||||||||||||||||||||
| //! | [`collect`] | Three-phase pipeline: collect items, analyze bodies, assemble final output; phase boundary is enforced structurally via the `(MonoItem, Item)` split and [`phased::Phased`] body wrapper | | ||||||||||||||||||||||||||||||||||
| //! | [`items`] | Constructing `(MonoItem, Item<Raw>)` pairs and extracting debug-level details | | ||||||||||||||||||||||||||||||||||
| //! | [`phased`] | [`Phased<T, S>`](phased::Phased) typestate wrapper encoding the post-monomorphization body invariant | | ||||||||||||||||||||||||||||||||||
| //! | [`mir_visitor`] | `BodyAnalyzer`: single-pass MIR body traversal collecting calls, allocs, types, spans | | ||||||||||||||||||||||||||||||||||
| //! | [`ty_visitor`] | `TyCollector`: recursively collects reachable types with layout info (some special kinds are traversed but not stored) | | ||||||||||||||||||||||||||||||||||
| //! | [`link_map`] | Function resolution map: type + instance kind to symbol name | | ||||||||||||||||||||||||||||||||||
|
|
@@ -49,6 +50,7 @@ mod collect; | |||||||||||||||||||||||||||||||||
| mod items; | ||||||||||||||||||||||||||||||||||
| mod link_map; | ||||||||||||||||||||||||||||||||||
| mod mir_visitor; | ||||||||||||||||||||||||||||||||||
| mod phased; | ||||||||||||||||||||||||||||||||||
| mod schema; | ||||||||||||||||||||||||||||||||||
| mod ty_visitor; | ||||||||||||||||||||||||||||||||||
| mod types; | ||||||||||||||||||||||||||||||||||
|
|
@@ -57,6 +59,7 @@ mod util; | |||||||||||||||||||||||||||||||||
| // Re-exports preserving the public API | ||||||||||||||||||||||||||||||||||
| pub use collect::collect_smir; | ||||||||||||||||||||||||||||||||||
| pub use items::MonoItemKind; | ||||||||||||||||||||||||||||||||||
| pub use phased::Mono; | ||||||||||||||||||||||||||||||||||
| pub use schema::{AllocInfo, FnSymType, Item, LinkMapKey, SmirJson, TypeMetadata}; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
59
to
63
|
||||||||||||||||||||||||||||||||||
| // Re-exports preserving the public API | |
| pub use collect::collect_smir; | |
| pub use items::MonoItemKind; | |
| pub use phased::Mono; | |
| pub use schema::{AllocInfo, FnSymType, Item, LinkMapKey, SmirJson, TypeMetadata}; | |
| // Public re-exports and backwards-compatible aliases | |
| pub use collect::collect_smir; | |
| pub use items::MonoItemKind; | |
| pub use phased::Mono; | |
| pub use schema::{AllocInfo, FnSymType, Item, LinkMapKey, SmirJson, TypeMetadata}; | |
| /// Backwards-compatible alias for the monomorphized `Item` phase. | |
| pub type ItemMono = Item<Mono>; | |
| /// Backwards-compatible alias for the monomorphized `MonoItemKind` phase. | |
| pub type MonoItemKindMono = MonoItemKind<Mono>; |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,103 @@ | ||||||||
| //! Typestate wrapper encoding the post-monomorphization body invariant. | ||||||||
| //! | ||||||||
| //! After the collection pipeline's fixpoint loop resolves all unevaluated | ||||||||
| //! constants, bodies stored in [`Item`](super::schema::Item) should contain | ||||||||
| //! no `ConstantKind::Unevaluated`. [`Phased<T, S>`] encodes this guarantee | ||||||||
| //! in the type system: phase 1+2 code works with `Phased<Body, Raw>`, and | ||||||||
| //! the phase 2 -> 3 boundary validates each body (via [`UnevaluatedChecker`]) | ||||||||
| //! before producing `Phased<Body, Mono>`. | ||||||||
| //! | ||||||||
| //! [`Phased`] serializes transparently (delegates to the inner `T`), so | ||||||||
| //! JSON output is unchanged. | ||||||||
|
|
||||||||
| use std::marker::PhantomData; | ||||||||
|
|
||||||||
| use crate::compat::serde; | ||||||||
|
||||||||
| use crate::compat::serde; |
Copilot
AI
Mar 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phased::into_inner is currently unused within the crate, and since phased is not a public module this will trigger the dead_code lint (“method is never used”) under CI’s --deny warnings. Consider removing it for now, or annotate it with an appropriate #[allow(dead_code)] if you want to keep it for future use.
| /// Consume the wrapper, returning the inner value. | |
| /// Consume the wrapper, returning the inner value. | |
| #[allow(dead_code)] |
Copilot
AI
Mar 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phased<Body, Raw>::validate calls UnevaluatedChecker.visit_body(...), but MirVisitor::visit_body requires &mut self. Calling it on the unit struct value will not compile; create a mutable UnevaluatedChecker instance (e.g., let mut checker = UnevaluatedChecker; checker.visit_body(...)).
| UnevaluatedChecker.visit_body(&self.0); | |
| let mut checker = UnevaluatedChecker; | |
| checker.visit_body(&self.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
body.cloned().unwrap()will panic when a function body is missing (which is explicitly handled later via the<empty body>branch). Consider handlingNonehere as well (e.g., skip locals rendering or emit an empty locals node) soto_dot_filecan render crates even when some bodies aren’t available.