Fix #3853: infer scoped locals from ref safety#3888
Draft
sailro wants to merge 2 commits into
Draft
Conversation
ScopedRefAttribute only records explicit syntax. Effective lifetime also depends on UnscopedRefAttribute, params collections, out parameters, and the defining module's RefSafetyRules version. Model those distinctions in the type system without changing decompiler output. Assisted-by: Copilot:gpt-5.6-sol:GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 86d2918e-5a24-48b4-9a86-41d331ec3720
Local scopedness is erased from IL and PDBs, so it can only be recovered from the body. Compare each declaration initializer with later assignments, field stores, and receiver captures using the C# 11 ref/value escape rules, and emit scoped only when a later operation is strictly narrower. Assisted-by: Copilot:gpt-5.6-sol:GitHub Copilot CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 86d2918e-5a24-48b4-9a86-41d331ec3720
This was referenced Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3853. Supersedes #3854. Depends on #3887.
Note
This is intentionally opened as a draft and is stacked on #3887. The current Files changed view also includes the foundation commit. Once #3887 merges, I will rebase this branch so this PR contains only the local-inference change.
tl;dr:
scopedon a local is erased from IL and PDBs, so type-system support cannot recoverthe modifier directly. This PR adds a late ILAst ref-safety analysis that emits
scopedonlywhen a later assignment or mutation is strictly narrower than the declaration initializer.
Problem
A local's
scopedmodifier has no metadata representation. Dropping it produces invalid C#when a wide initializer is followed by a narrower operation:
stackalloc, CS8353A shape-only check is not sufficient. It can both miss required modifiers and add redundant
ones when the initializer is already narrow.
Solution
Add
IntroduceScopedModifierOnLocals, a lateIILTransformthat mirrors Roslyn's ref-safetymodel:
out, struct receivers, ref-to-ref-structreturns, fields, conditionals, null coalescing, and unknown signatures
StLocassignments, field stores, and captures into writable instance orclassic ref extension receivers
scopedThe transform records the result on
ILVariable.IsScoped.DeclareVariablesonly renders themodifier, following the existing
IntroduceRefReadOnlyModifierOnLocalspattern.Tests
The
Pretty/RefFieldsRoslyn 4+ matrix covers:propagation
not cause
scopedValidation:
Review focus
The main review area is the transfer logic in
IntroduceScopedModifierOnLocals, especiallyinvocation escape and receiver-capture rules.