Skip to content

Commit 139fce8

Browse files
hyperpolymathclaude
andcommitted
feat: add region-linear fusion types to ephapaxiser
Extends the ephapaxiser ABI to support region-scoped resource tracking, mirroring the Ephapax compiler's region-linear fusion: - LinearResource: add `region: Option<String>` field to track which region a resource belongs to - Violation: add RegionEscape and RegionLinearNotConsumed variants - Display: format new violations with region context - analyzer: set region to None (Phase 2 will populate via scope analysis) All 45 tests pass. The region field is opt-in — existing ephapaxiser manifests work unchanged. Phase 2 will add `[[regions]]` to the manifest format and scope-aware analysis to the codegen pipeline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0975e22 commit 139fce8

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

src/abi/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ pub struct LinearResource {
146146
pub state: OwnershipState,
147147
/// Where this resource was allocated (set during analysis).
148148
pub allocation_site: Option<SourceLocation>,
149+
/// Which region this resource belongs to (if any).
150+
///
151+
/// When set, the resource's lifetime is bounded by the region — it cannot
152+
/// escape the region's scope. At region exit, all linear resources in the
153+
/// region must have been consumed (AllLinearsConsumed from the formal proofs).
154+
/// This field mirrors Ephapax's region-linear fusion: the region constraint
155+
/// is orthogonal to the ownership state tracking.
156+
pub region: Option<String>,
149157
}
150158

151159
impl LinearResource {
@@ -158,6 +166,7 @@ impl LinearResource {
158166
kind,
159167
state: OwnershipState::Uninitialized,
160168
allocation_site: None,
169+
region: None,
161170
}
162171
}
163172
}
@@ -183,6 +192,24 @@ pub enum Violation {
183192
/// Where the second (invalid) deallocation occurred.
184193
second_free: SourceLocation,
185194
},
195+
/// Resource escapes its region scope — region escape.
196+
RegionEscape {
197+
/// Name of the escaping resource.
198+
resource_name: String,
199+
/// The region the resource belongs to.
200+
region: String,
201+
/// Where the escape was detected.
202+
escape_site: SourceLocation,
203+
},
204+
/// Linear resource in a region not consumed before region exit.
205+
RegionLinearNotConsumed {
206+
/// Name of the unconsumed resource.
207+
resource_name: String,
208+
/// The region that is exiting.
209+
region: String,
210+
/// Where the resource was allocated.
211+
allocation_site: SourceLocation,
212+
},
186213
/// Resource was used after being deallocated — use-after-free.
187214
UseAfterFree {
188215
/// Name of the misused resource.
@@ -207,6 +234,20 @@ impl fmt::Display for Violation {
207234
resource_name, first_free, second_free
208235
)
209236
}
237+
Self::RegionEscape { resource_name, region, escape_site } => {
238+
write!(
239+
f,
240+
"REGION-ESCAPE: '{}' in region '{}' escapes at {}",
241+
resource_name, region, escape_site
242+
)
243+
}
244+
Self::RegionLinearNotConsumed { resource_name, region, allocation_site } => {
245+
write!(
246+
f,
247+
"REGION-LINEAR-NOT-CONSUMED: '{}' in region '{}' allocated at {} not consumed before region exit",
248+
resource_name, region, allocation_site
249+
)
250+
}
210251
Self::UseAfterFree { resource_name, free_site, use_site } => {
211252
write!(
212253
f,

src/codegen/analyzer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ pub fn analyse(
167167
kind: var.kind.clone(),
168168
state: var.state.clone(),
169169
allocation_site: Some(var.allocation_site.clone()),
170+
region: None, // Phase 2: populated when scope-aware analysis is added.
170171
});
171172
}
172173

0 commit comments

Comments
 (0)