Commit Graph

37 Commits

Author SHA1 Message Date
Michael Gottesman 2e91725b3c [VariableNameUtils] Recover name for lazy global via addressor
When a @MainActor or lazy global is accessed its value flows through an
unsafeMutableAddressor function that returns Builtin.RawPointer, then
pointer_to_address, then load. The addressor has no self so the existing
nameThroughSelf path returned nothing, leaving the name as 'unknown'.

Fall back to using the callee name from the addressor apply when no self
is present. In a full compilation getDeclRef() resolves the AccessorDecl
back to the VarDecl name (e.g. 'globalKlass'); in SIL unit tests the
function name itself is used as the component.

rdar://179181114
2026-06-09 19:16:13 -07:00
Michael Gottesman d975fa027e [VariableNameUtils] Look through init_existential_ref/addr when inferring variable names
Without this, the name inferrer gave up at init_existential_ref (used when
wrapping a concrete value in `any Protocol`) and region isolation diagnostics
fell back to the generic "unknown pattern" catch-all instead of naming the
variable.

Also suppress the `.some` path component when looking through Optional.some
EnumInst wrapping, since users never write `x.some` in source and the suffix
produced confusing diagnostics like "'negotiator.some' cannot be returned".

Adds a lit test covering the regression case: a value stored to an
`inout sending` closure parameter and returned through an existential.

rdar://178775464
2026-06-07 13:44:57 -07:00
Michael Gottesman 9b9b460666 [SILOptimizer] VariableNameInferrer: name call results after their callee
VariableNameInferrer previously failed to infer a name for the result of
a call when the result carried no other debug info. In particular:

  - 'try_apply' results were never handled at all: the result is
    delivered as the normal successor's block argument, so it has no
    defining instruction and never reached the apply-handling code.
  - The 'function_ref'-with-self path pushed the callee's *decl context*
    name (often '<unknown decl>') rather than the callee's own name.
  - A bare call result (no self, no debug info) was left unnamed.

As a result, region-isolation diagnostics such as the 'inout sending'
returned-value error fell through to the catch-all "please file a bug"
unknown-pattern diagnostic for ordinary code like:

    func f(mutex: borrowing Mutex<[NS]>) -> [NS] {
        mutex.withLock { items in items.filter { _ in true } }
    }

Now a name is recovered uniformly for apply / try_apply / begin_apply
results:

  - If the callee has a self argument, walk into self and produce
    'self.member'.
  - Otherwise, name the result after the callee function itself.

The 'filter' example above now produces a clear, named diagnostic
("'items.filter' cannot be returned") instead of the unknown-pattern
error.

Adds naming tests for apply/try_apply/begin_apply results (with and
without self), and updates two move-only diagnostics whose inferred
names improved from 'unknown' to 'self.<accessor>'.

rdar://178534561
2026-06-02 09:40:41 -07:00
Michael Gottesman 35323b0689 [region-isolation] Reword merge-region diagnostics so we never fail on missing names
Restructure the five "incompatible region merge" diagnostics emitted by
IncompatibleRegionMergeDiagnosticEmitter so that the primary error never
depends on recovering a value name. Previously, when VariableNameInferrer
could not infer a name for either side of the merge, every emitter fell
back to emitUnknownPatternError() and the user got the unhelpful "we do
not understand this pattern" diagnostic for a violation the analysis had
in fact understood.

Now:

* Each primary states the *operation* that performs the merge and the
  two isolation domains involved -- e.g. "passing arguments to %kind2
  could allow for references between values exposed to %0 and %1 code,
  risking data races". The primary requires only the isolation strings
  and (where applicable) the callee decl or cast target type.

* Per-value details move to follow-up notes anchored at each value's
  *defining* source location (parameter decl for SILFunctionArgument,
  defining-instruction loc otherwise) so the user can see where each
  side came from. Two note variants: named ("'self.x' is exposed to ...
  code") when name inference succeeds, bare ("value is exposed to ...
  code") otherwise. We deliberately do not emit a "value of type T"
  variant because SIL values often do not carry a reliable AST type.

* The shared emitMergeRegionValueNote() helper centralises note
  emission and the new preciseSourceLocForValue() helper picks the
  most precise SourceLoc available for a value.

emitNonisolatedFunction now falls through to emitUnknown rather than
emitUnknownPatternError when ApplySite/getCalleeDeclRef recovery fails,
so the primary still fires with isolation information in those cases.
emitUnknownPatternError remains reachable only when isolation info
itself is invalid -- a genuinely unknown pattern.

rdar://175592408
2026-05-26 14:49:29 -07:00
Joe Groff 097b0d3400 SIL: Split unchecked_*_enum_data_addr according to ownership and effects.
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:

- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
  projection. It is only allowed for enums whose projection operation is
  nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
  invalidating the enum and leaving the payload to be further consumed.
  This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
  The instruction takes a second operand for "scratch" space, which the
  enum representation may be copied into in order to avoid invalidating the
  enum value, so the result is dependent on the lifetime of both the
  original enum and the scratch buffer. This allows for borrowing switches
  over resilient enums.

`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.

Fixes rdar://174952822.
2026-04-27 15:40:37 -07:00
Kavon Farvardin 6b858b411c ManualOwnership: introduce 'DynamicExclusivity'
We can add warnings about dynamic exclusivity
checks that may happen on an access, with
explainers about why they happen for safety.
2025-10-24 16:59:44 -07:00
Meghana Gupta 75d040f257 Update VariableNameInferrer for borrow/mutate accessors 2025-10-02 07:18:25 -07:00
Anthony Latsis a84dfc8387 [Gardening] Fix some set but not used variables 2025-01-30 21:34:38 +00:00
Andrew Trick fc9d0b3340 [MoveOnlyAddrChecker] fix VariableNameInferrer for mark_depends
Fix the use-def address walk to pass through mark_dependence to find a variable
introducer with a debug_value use.
2024-10-22 09:28:54 -07:00
Michael Gottesman 2dd1ef2322 Merge pull request #75759 from gottesmm/variable-name-utils-refactor
[variable-name-utils] Change internal representation to use StringRef instead of a SILValue
2024-08-07 19:37:46 -07:00
Michael Gottesman 0039b286b5 [variable-name-inference] Eliminate the old value representation and just use StringRef. 2024-08-07 13:14:50 -07:00
Michael Gottesman 98fd04c3cd [variable-name-utils] Convert function_ref and method_inst to use the new StringRef form 2024-08-07 13:14:50 -07:00
Michael Gottesman aa5db257ce [variable-name-utils] Move destructure and function arg to the new string ref representation. 2024-08-07 13:14:50 -07:00
Michael Gottesman 63b67389b0 [variable-name-utils] Convert all DebugVarCarryingInst|VarDeclCarryingInst to the new representation of storing a StringRef. 2024-08-07 13:14:50 -07:00
Michael Gottesman 76f67cf092 [variable-name-utils] Convert all gep like instructions except ref_element_addr to be put on the stack as StringRefs instead of values. 2024-08-07 13:14:50 -07:00
Michael Gottesman 765d3ba039 [variable-name-utils] Convert debug_value to StringRef form.
Just doing the refactoring.
2024-08-07 13:14:50 -07:00
Michael Gottesman 3d85f47671 [variable-name-utils] Store a std::variant instead of a pointer union and add the ability to append StringRef.
CONTEXT: This code works by building up a stack of SIL values of values that
need to be transformed into a StringRef as part of generating our name path and
then as a second phase performs the conversion of those values to StringRef as
we pop from the stack.

This is the first in a string of commits that are going to refactor
VariableNameUtils so that the stack will only contain StringRef instead of SIL
entities. This will be accomplished by moving the SIL value -> StringRef code
from the combining part of the algorithm (where we drain the stack) to the
construction of the stack.

The reason why I am doing this is two fold:

1. By just storing StringRef into the stack I am simplifying the code. Today as
mentioned above in the context, we gather up the SILValue we want to process and
then just convert them to StringRef. This means that any time one has to add a
new instruction, one has to update two different pieces of code. By trafficking
in StringRef instead, one only has to update one piece of code.

2. I want to add some simple code that allows for us to get names from closures
which would require me to recurse. I am nervous about putting
values/instructions from different functions in the same data structure. Today
it is safe, but it is bad practice. Instead, by just using StringRef in the
stack, I can avoid this problem.
2024-08-07 13:14:50 -07:00
Michael Gottesman 2e138024a8 [variable-name-utils] Look through convert function when finding names. 2024-08-07 13:10:54 -07:00
Nate Chandler a75bd893b9 [Test] Underscored variable_name_inference.
Use underscores rather than hyphens so that text editors understand the
name as a single word.
2024-07-25 13:52:21 -07:00
Michael Gottesman bcbf5c515e [region-isolation] Emit an error when we assign a non-disconnected value into a sending result.
rdar://127318392
2024-07-18 21:29:08 -07:00
Michael Gottesman b5aa2fec31 [siloptimizer] Teach VariableNameInference how to look through convert_escape_to_no_escape.
This was causing us to emit old style diagnostics in certain cases.

Just doing a walk through of the diagnostics and fixing issues while I
am here sprucing up sending diagnostics.

rdar://130915737
2024-07-01 14:37:11 -07:00
Michael Gottesman baec06ed23 [variable-name-inference] Add support for handling EndInitLetRefInst. 2024-06-24 18:16:11 -07:00
Tim Kientzle 1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Michael Gottesman 51ef67d7df [variable-name-utils] Refactor inferName/inferNameAndRoot helpers onto VariableNameInferrer.
I have been using these in TransferNonSendable and they are useful in terms of
reducing the amount of code that one has to type to use this API. I am going to
need to use it in SILIsolationInfo, so it makes sense to move it into
SILOptimizer/Utils.

NFCI.
2024-04-11 15:41:18 -07:00
Michael Gottesman 20c24293e5 [region-isolation] Do not look through begin_borrow or move_value if they are marked as a var_decl.
The reason why we do this is that we want to treat this as a separate value from
their operand since they are the result of defining a new value.

This has a few nice side-effects, one of which is that if a let results in just
a begin_borrow [var_decl], we emit names for it.

I also did a little work around helping variable name utils to lookup names from
applies that are fed into a {move_value,begin_borrow} [var_decl] which then has
the debug_value we are searching for.
2024-04-11 15:41:18 -07:00
Michael Gottesman ce27305279 [sil] Teach variable name utils how to handle init_existential_addr temporaries.
Just eliminating more cases of the typed errors in favor of named errors.
2024-03-29 18:48:04 -07:00
Michael Gottesman 29e3069a50 [region-isolation] Teach variable name utils how to handle more tuple patterns.
Just slicing off from a larger patch.
2024-03-19 13:19:09 -07:00
Michael Gottesman 8b899b8f71 [region-isolation] Teach variable_name_inference how to infer through store_borrow initialized variables.
This eliminates a bunch of cases where we couldn't infer the name of a variable
and used the type based diagnostic.

It also eliminates an 'unknown' case for move checking.
2024-03-19 13:19:09 -07:00
Michael Gottesman f2b5b86e2e [region-isolation] Learn how to find variable names around phi arguments.
With this, the only remaining "task or actor isolated" error is due to changes I
need to land around async let.
2024-03-12 13:43:02 -07:00
Michael Gottesman ec81ecdbe6 [region-isolation] Eliminate more of the 'task or actor isolated value cannot be transferred' warning.
Specifically, I had to teach the variable name inferrer how to infer through
unchecked_enum_data and unchecked_take_enum_data_addr.
2024-03-12 12:26:55 -07:00
Michael Gottesman e21c0a6c39 [sil] Teach variable name inference how to look through more instructions. 2024-02-22 13:50:06 -08:00
Michael Gottesman e1ecd8b54d [sil] Teach VariableNameUtils how to look through function conversion thunk patterns. 2024-02-22 13:50:06 -08:00
Michael Gottesman 9154082d12 [sil] Teach VariableNameInferrer how to look through /all/ accessors. 2024-02-22 13:50:06 -08:00
Michael Gottesman d4f727adde [region-isolation] Add support for identifying names when a temporary is initialized with a store. 2024-02-06 16:49:30 -08:00
Michael Gottesman 7df13b3c1f [sil] Refactor VariableNameUtils for handling more kinds of writes to temporaries. 2024-02-06 16:18:34 -08:00
Michael Gottesman 2010579b02 [sil] Add basic test support for variable name inference. 2024-02-06 15:21:11 -08:00
Michael Gottesman a569160f21 [sil] Refactor out the variable name inferer from MoveOnlyDiagnostics.cpp -> VariableNameUtils.
I am going to reuse this for TransferNonSendable. In the process I made a few
changes to make it more amenable to both use cases and used the current set of
tests that we have for noncopyable types to validate that I didn't break
anything.
2024-02-06 13:42:35 -08:00