Retain only source backing guard after exact policy transfer
This commit is contained in:
@@ -47,7 +47,7 @@ pub(super) struct ParsedMixedSyntax<'s> {
|
|||||||
// phase adds syntax entries to this once, not tokens/positions again.
|
// phase adds syntax entries to this once, not tokens/positions again.
|
||||||
metadata: usize,
|
metadata: usize,
|
||||||
// Kept through consumed resolution/indexing; fixes the live backing owner.
|
// Kept through consumed resolution/indexing; fixes the live backing owner.
|
||||||
carried: Option<carried::CarriedInput<'s>>,
|
carried: Option<carried::CarriedGuard<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileSyntax<'s> {
|
struct FileSyntax<'s> {
|
||||||
@@ -257,7 +257,7 @@ fn parse_impl<'s>(
|
|||||||
bundle: &'s SourceBundle,
|
bundle: &'s SourceBundle,
|
||||||
limits: ProjectLimits,
|
limits: ProjectLimits,
|
||||||
profile: Limits,
|
profile: Limits,
|
||||||
carried: Option<carried::CarriedInput<'s>>,
|
carried: Option<carried::CarriedGuard<'s>>,
|
||||||
) -> Result<ParsedMixedSyntax<'s>, Vec<SourceDiagnostic>> {
|
) -> Result<ParsedMixedSyntax<'s>, Vec<SourceDiagnostic>> {
|
||||||
let entry_source = bundle.files.get(&bundle.entry).map_or("", String::as_str);
|
let entry_source = bundle.files.get(&bundle.entry).map_or("", String::as_str);
|
||||||
let at_entry = |error| located(&bundle.entry, entry_source, ordinary_error(error));
|
let at_entry = |error| located(&bundle.entry, entry_source, ordinary_error(error));
|
||||||
|
|||||||
@@ -26,23 +26,44 @@ enum SnapshotBacking<'s> {
|
|||||||
pub(super) struct CarriedInput<'s> {
|
pub(super) struct CarriedInput<'s> {
|
||||||
backing: SnapshotBacking<'s>,
|
backing: SnapshotBacking<'s>,
|
||||||
}
|
}
|
||||||
|
enum GuardBacking<'s> {
|
||||||
|
Borrowed,
|
||||||
|
Retained(&'s RetainedSnapshot),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Policy has transferred into Budget/ParsedMixedSyntax. Only backing ownership
|
||||||
|
/// remains here, avoiding a duplicate inline policy in every later witness.
|
||||||
|
pub(super) struct CarriedGuard<'s> {
|
||||||
|
backing: GuardBacking<'s>,
|
||||||
|
}
|
||||||
impl<'s> CarriedInput<'s> {
|
impl<'s> CarriedInput<'s> {
|
||||||
fn policy(&self) -> &SnapshotPolicy {
|
fn into_parts(self) -> (&'s SourceBundle, SnapshotPolicy, CarriedGuard<'s>) {
|
||||||
match &self.backing {
|
match self.backing {
|
||||||
SnapshotBacking::Borrowed { policy, .. } => policy,
|
SnapshotBacking::Borrowed { bundle, policy } => (
|
||||||
SnapshotBacking::Retained(owner) => &owner.policy,
|
bundle,
|
||||||
}
|
policy,
|
||||||
}
|
CarriedGuard {
|
||||||
fn bundle(&self) -> &'s SourceBundle {
|
backing: GuardBacking::Borrowed,
|
||||||
match &self.backing {
|
},
|
||||||
SnapshotBacking::Borrowed { bundle, .. } => bundle,
|
),
|
||||||
SnapshotBacking::Retained(owner) => &owner.bundle,
|
SnapshotBacking::Retained(owner) => (
|
||||||
|
&owner.bundle,
|
||||||
|
SnapshotPolicy {
|
||||||
|
limits: owner.policy.limits,
|
||||||
|
project_limits: owner.policy.project_limits,
|
||||||
|
},
|
||||||
|
CarriedGuard {
|
||||||
|
backing: GuardBacking::Retained(owner),
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl CarriedGuard<'_> {
|
||||||
pub(super) fn slots(&self) -> Slots {
|
pub(super) fn slots(&self) -> Slots {
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
SnapshotBacking::Borrowed { .. } => Slots::default(),
|
GuardBacking::Borrowed => Slots::default(),
|
||||||
SnapshotBacking::Retained(owner) => owner.retained,
|
GuardBacking::Retained(owner) => owner.retained,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(super) fn check(
|
pub(super) fn check(
|
||||||
@@ -63,9 +84,8 @@ impl<'s> CarriedInput<'s> {
|
|||||||
|
|
||||||
/// Input already binds the actual bundle; callers cannot supply a replacement.
|
/// Input already binds the actual bundle; callers cannot supply a replacement.
|
||||||
fn parse_carried(input: CarriedInput<'_>) -> Result<ParsedMixedSyntax<'_>, Vec<SourceDiagnostic>> {
|
fn parse_carried(input: CarriedInput<'_>) -> Result<ParsedMixedSyntax<'_>, Vec<SourceDiagnostic>> {
|
||||||
let bundle = input.bundle();
|
let (bundle, policy, guard) = input.into_parts();
|
||||||
let policy = input.policy();
|
parse_impl(bundle, policy.project_limits, policy.limits, Some(guard))
|
||||||
parse_impl(bundle, policy.project_limits, policy.limits, Some(input))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ fn real_retained_bundles_keep_exact_guard_work_and_once_only_resolved_baseline()
|
|||||||
assert_eq!(parsed.budget.numeric_units(), 0);
|
assert_eq!(parsed.budget.numeric_units(), 0);
|
||||||
assert!(std::ptr::eq(parsed.bundle, &owner.bundle));
|
assert!(std::ptr::eq(parsed.bundle, &owner.bundle));
|
||||||
assert!(
|
assert!(
|
||||||
matches!(&parsed.carried.as_ref().unwrap().backing,SnapshotBacking::Retained(retained) if std::ptr::eq(*retained,&owner))
|
matches!(&parsed.carried.as_ref().unwrap().backing,GuardBacking::Retained(retained) if std::ptr::eq(*retained,&owner))
|
||||||
);
|
);
|
||||||
let resolved = project::resolve(parsed).unwrap();
|
let resolved = project::resolve(parsed).unwrap();
|
||||||
assert_eq!(resolved.project(), &expected_project());
|
assert_eq!(resolved.project(), &expected_project());
|
||||||
@@ -320,12 +320,19 @@ fn explicit_fault_injections_cover_occurrence_caps_and_unreachable_overflows() {
|
|||||||
let budget = Budget::new(profile(100, 1024)).unwrap();
|
let budget = Budget::new(profile(100, 1024)).unwrap();
|
||||||
// Valid hard limits reject C first: direct injection reaches arithmetic.
|
// Valid hard limits reject C first: direct injection reaches arithmetic.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
held.input().check(&budget, 0, 1).unwrap_err().message,
|
held.input()
|
||||||
|
.into_parts()
|
||||||
|
.2
|
||||||
|
.check(&budget, 0, 1)
|
||||||
|
.unwrap_err()
|
||||||
|
.message,
|
||||||
"Mixed auxiliary storage size overflow."
|
"Mixed auxiliary storage size overflow."
|
||||||
);
|
);
|
||||||
held.retained = Slots::default();
|
held.retained = Slots::default();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
held.input()
|
held.input()
|
||||||
|
.into_parts()
|
||||||
|
.2
|
||||||
.check(&budget, usize::MAX, 1)
|
.check(&budget, usize::MAX, 1)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.message,
|
.message,
|
||||||
|
|||||||
@@ -19,3 +19,13 @@ Zero carried mode intentionally refuses E cap 11 at preprojection, while legacy
|
|||||||
No Cargo/build/test execution was performed by the implementation agent. Targeted rustfmt on owned files and raw-LF normalization are authoring checks only. Parent owns source review integration, exact-source commits, compiler/focused/full-suite gates and publication. Inherited full-suite failures and formatting issues are not addressed by this patch; parent gates will compare actual outcomes. The documented environment-sensitive upstream stack observation remains a limitation. Existing small-stack controls were not edited or waived.
|
No Cargo/build/test execution was performed by the implementation agent. Targeted rustfmt on owned files and raw-LF normalization are authoring checks only. Parent owns source review integration, exact-source commits, compiler/focused/full-suite gates and publication. Inherited full-suite failures and formatting issues are not addressed by this patch; parent gates will compare actual outcomes. The documented environment-sensitive upstream stack observation remains a limitation. Existing small-stack controls were not edited or waived.
|
||||||
|
|
||||||
Independent test-source review corrected two pre-execution fixture mistakes: use the accepted oa_property/sa_property keywords, and distinguish the parser include-edge error span 0..1 from the traversal include-depth span 0..23. These are source-review corrections, not recorded runtime failures.
|
Independent test-source review corrected two pre-execution fixture mistakes: use the accepted oa_property/sa_property keywords, and distinguish the parser include-edge error span 0..1 from the traversal include-depth span 0..23. These are source-review corrections, not recorded runtime failures.
|
||||||
|
|
||||||
|
## Recorded regression and slim-guard candidate
|
||||||
|
|
||||||
|
Parent's `d11b99bb` focused run passed all 12 carried tests, but its full run aborted at the unchanged `ordinary_index::tests::small_stack_success_and_late_header_failure_leave_no_partial_owner` with STATUS_STACK_OVERFLOW. The predecessor `18073a6f` full run had completed with 230 passing tests and 16 inherited failures, including that control. This is a failed current full gate, not an inherited-failure waiver or an accepted repair.
|
||||||
|
|
||||||
|
The exact-artifact LLDB trace reproduces the overflow during Windows heap allocation under formatting/Exact::parse_decimal, then exact_literal, syntax::binding, declarations::parse, State::parse_typed, Parser::unit, new parse_impl, parse_with_profile, parse, accepted/indexed helpers and the existing worker. The diagnostic child's killed exit is not a test pass. Parent measured individual prologues of parse_impl 11,144 bytes, parse_with_profile 312, accepted 1,752, indexed 1,704 and worker 7,752; these are not the complete active stack. Raw evidence remains in the parent gate records, including `carried-debugger-d11b99b-1.log` and `carried-full-d11b99b-1.stack-frames.json`.
|
||||||
|
|
||||||
|
The selected narrow candidate consumes CarriedInput before entering the shared parser. Exact captured policy transfers into Budget and syntax.limits; the retained CarriedGuard holds only Borrowed or Retained(&RetainedSnapshot). This removes the duplicate inline SnapshotPolicy payload from parsed/resolved/indexed/result carriers, while retained backing still borrows the actual allocation-owning bundle. Borrowed source identity remains bound through ParsedMixedSyntax.bundle. Explicit Some mode still distinguishes carried zero from legacy None, and all checks/reservations/Usage remain unchanged. No heap allocation or new logical storage was introduced. The parser wrapper remains uninlined and unchanged.
|
||||||
|
|
||||||
|
Only carried tests' guard-shape inspection and direct injected-arithmetic access follow the new internal guard type; all expected counts, limits, spans, outcomes and existing stack tests remain unchanged. The candidate is not claimed to establish a sole overflow cause or a successful repair before parent exact-source gates. All original failure evidence remains retained.
|
||||||
|
|||||||
Reference in New Issue
Block a user