Skip to content

Conversation

@atrick
Copy link
Contributor

@atrick atrick commented Oct 22, 2025

Fix miscompilations involving MutableSpan.

  • [NFC] add a new entry point for DiagnoseDependence.reportError
    Allow diagnosing values that have no relevant users. Such as an @inout argument.

  • [NFC] LifetimeDependenceDefUseWalker.inoutDependence entry point
    Handle cases where there's no relevant operand.

  • [NFC] Add ApplySite.fullyAssigns(Operand) query

  • Fix LifetimeDependenceDefUseWalker for @inout reassignment

  • Extend AddressInitializationWalker.findSingleInitializer
    Handle applies that reassign the lifetime of their operand vs. the value of
    their operand.

  • LocalVariableReachableAccess: handle lifetime reassignment
    A ~Escapable inout apply operand that does not propagate its own lifetime can be
    treated as being assigned a new lifetime in the caller.

    @Lifetime(arg: copy source)
    func foo<T: ~Escapable>(arg: inout T, source: T) {
    arg = source
    }

    A call to 'foo' initializes the lifetime of 'arg', thereby ending the lifetime
    of the previous value.

  • [NFC] Rename ArgumentConventions.parameterIndex(ofArgumentIndex:)

  • [NFC] Add ApplySite.parameterDependence(target:source:)

  • Fix LifetimeDependenceDefUseWalker to follow inout dependence
    Fixes rdar://157796728 ([nonescapable] [miscompile] No diagnostic error when an
    inout MutableSpan is reassigned to a different lifetime source)

  • [NFC] LocalVariableAccessInfo.description

  • LocalVariableUtils add non-escaping closure capture support
    Don't always consider an inout_aliasable argument to have
    escaped. AccessEnforcementSelection has already done that analysis and left
    begin_access [dynamic] artifacts if the argument has escaped in any meaningful
    way. Use that information to

    Essential for supporting autoclosures that call mutating methods on span-like
    things. Such as UTF8Span.UnicodeScalarIterator.skipForward():

    e.g. while numSkipped < n && skipForward() != 0 { ... }

  • [NFC] extend AddressInitializationWalker to report address reads

  • Fix LocalVariableReachableAccess to handle potential reassignment.
    Define LocalAccessInfo._isFullyAssigned to mean that the access does not read
    the incoming value. Then treat any assignment that isn't full as a potential read.

  • LocalVariableUtils: precisely handle function live-out
    Only record an outgoingArgument access when the current allocation is an
    outgoing argument and the function exiting instruction is ReturnInst.

    This avoids invalid SIL where we attempt to extend end_access up to an unwind but
    fail to actually materialize that end_access.

  • Test lifetime reassignment

  • Test noescape closure capture lifetimes

  • Update tests for local variable reachability for debug output

  • Update lifetime tests for improved diagnostics

@atrick atrick requested a review from eeckstein as a code owner October 22, 2025 23:35
@atrick
Copy link
Contributor Author

atrick commented Oct 22, 2025

@swift-ci test

@atrick atrick requested a review from meg-gupta October 22, 2025 23:36
@atrick
Copy link
Contributor Author

atrick commented Oct 23, 2025

@swift-ci test

atrick added 19 commits October 23, 2025 23:34
Handle applies that reassign the lifetime of their operand vs. the value of
their operand.
Allow diagnosing values that have no relevant users. Such as an @inout argument.
Handle cases where there's no relevant operand.
Define LocalAccessInfo._isFullyAssigned to mean that the access does not read
the incoming value. Then treat any assignment that isn't full as a potential read.
Fixes rdar://157796728 ([nonescapable] [miscompile] No diagnostic error when an
inout MutableSpan is reassigned to a different lifetime source)
Don't always consider an inout_aliasable argument to have
escaped. AccessEnforcementSelection has already done that analysis and left
begin_access [dynamic] artifacts if the argument has escaped in any meaningful
way. Use that information to

Essential for supporting autoclosures that call mutating methods on span-like
things. Such as UTF8Span.UnicodeScalarIterator.skipForward():

e.g. while numSkipped < n && skipForward() != 0 { ... }
Only record an outgoingArgument access when the current allocation is an
outgoing argument and the function exiting instruction is ReturnInst.

This avoids invalid SIL where we attempt to extend end_access up to an `unwind` but
fail to actually materialize that end_access.
@atrick
Copy link
Contributor Author

atrick commented Oct 24, 2025

@swift-ci test

@atrick atrick merged commit 5494a24 into swiftlang:main Oct 24, 2025
5 checks passed
@atrick atrick deleted the lifedep-reassign branch October 24, 2025 16:55
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.

1 participant