Skip to content

Preventing infinite inlining of cycle functions.#9917

Merged
orizi merged 1 commit into
mainfrom
orizi/05-08-preventing_infinite_inlining_of_cycle_functions
May 10, 2026
Merged

Preventing infinite inlining of cycle functions.#9917
orizi merged 1 commit into
mainfrom
orizi/05-08-preventing_infinite_inlining_of_cycle_functions

Conversation

@orizi
Copy link
Copy Markdown
Collaborator

@orizi orizi commented May 10, 2026

Summary

Fixes a hang that occurred when lowering self-referential Destruct implementations in no-gas mode (issue #9894). The cycle detection for inlining now uses LoweringStage::PreOptimizations instead of LoweringStage::Monomorphized, which correctly identifies recursive destructors as cyclic and prevents infinite inlining. The TODO comment about needing better logic to avoid inlining destructors that call themselves has been removed, as this fix addresses that concern.

A no_gas test flag and corresponding LoweringDatabaseForTesting::with_no_gas() snapshot are introduced to enable lowering tests that disable withdraw_gas insertion, along with a regression test covering the self-referential Destruct case.


Type of change

Please check one:

  • Bug fix (fixes incorrect behavior)
  • New feature
  • Performance improvement
  • Documentation change with concrete technical impact
  • Style, wording, formatting, or typo-only change

Why is this change needed?

In no-gas mode, a struct with a Destruct impl that calls itself (directly or indirectly) caused the compiler to hang indefinitely during inlining. The cycle check was running against LoweringStage::Monomorphized, which did not detect the cycle at the point where inlining decisions are made, allowing unbounded recursive inlining attempts.


What was the behavior or documentation before?

Compiling a self-referential Destruct impl with gas disabled would cause the compiler to hang without producing diagnostics or output.


What is the behavior or documentation after?

The compiler correctly detects the cycle, skips inlining for the recursive destructor, and produces valid lowered output without hanging.


Related issue or discussion (if any)

Fixes #9894


Additional context

The SHARED_DB static in test_utils.rs was also changed from pub to private, as it was not intended to be part of the public API.

@reviewable-StarkWare
Copy link
Copy Markdown

This change is Reviewable

Copy link
Copy Markdown
Collaborator Author

orizi commented May 10, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 10, 2026

PR Summary

Medium Risk
Changes the inliner’s cycle detection stage, which can alter inlining behavior and generated lowered code in recursive/cyclic call scenarios. Adds new no-gas testing mode and regression coverage, reducing risk of future hangs but still touching compiler optimization logic.

Overview
Fixes an inlining hang in no-gas lowering by switching the inliner’s cycle check in priv_should_inline to use LoweringStage::PreOptimizations, preventing recursive/cyclic callees (notably self-referential Destruct impls) from being inlined indefinitely.

Extends the lowering test runner with a no_gas flag backed by LoweringDatabaseForTesting::with_no_gas() (disables ADD_WITHDRAW_GAS) and adds a regression case in test_data/cycles; also removes an outdated TODO about destructor self-inlining.

Reviewed by Cursor Bugbot for commit 7789074. Bugbot is set up for automated code reviews on this repo. Configure here.

Copy link
Copy Markdown
Collaborator

@TomerStarkware TomerStarkware left a comment

Choose a reason for hiding this comment

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

:lgtm:

@TomerStarkware reviewed 4 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on orizi).

@orizi orizi changed the base branch from orizi/05-07-refactor_lowering_made_function_not_return_maybe_and_possibly_hide_diags to graphite-base/9917 May 10, 2026 08:28
@orizi orizi force-pushed the graphite-base/9917 branch from dd3b75b to d534bf9 Compare May 10, 2026 08:28
@orizi orizi force-pushed the orizi/05-08-preventing_infinite_inlining_of_cycle_functions branch from a9293b1 to 7789074 Compare May 10, 2026 08:28
@orizi orizi changed the base branch from graphite-base/9917 to main May 10, 2026 08:28
@orizi orizi enabled auto-merge May 10, 2026 08:29
@orizi orizi added this pull request to the merge queue May 10, 2026
Merged via the queue into main with commit ac2d27e May 10, 2026
105 checks passed
@orizi orizi deleted the orizi/05-08-preventing_infinite_inlining_of_cycle_functions branch May 10, 2026 11:00
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.

bug: (unbounded memory allocation) Compiler hangs and allocates unbounded memory when a manual Destruct<T> impl body does not consume self

3 participants