Skip to content

Commit 5943d40

Browse files
committed
LifetimeDependenceDiagnostics: handle dynamic casting of Span<T>
Add a special case for checked_cast_addr_br instruction. If it conformed to SourceDestAddrInstruction, then the diagnostics would already have handled it naturally, but the instruction's conditional semantics are strange enough that such a conformance might confuse other passes. rdar://159793739 (Using `as?` with non-escapable types emits faulty lifetime diagnostics)
1 parent e11f7f1 commit 5943d40

File tree

4 files changed

+33
-2
lines changed

4 files changed

+33
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,8 @@ extension LifetimeDependenceDefUseWalker {
10721072
return loadedAddressUse(of: localAccess.operand!, intoValue: load)
10731073
case let copyAddr as SourceDestAddrInstruction:
10741074
return loadedAddressUse(of: localAccess.operand!, intoAddress: copyAddr.destinationOperand)
1075+
case let castAddr as CheckedCastAddrBranchInst:
1076+
return loadedAddressUse(of: localAccess.operand!, intoAddress: castAddr.destinationOperand)
10751077
case is SwitchEnumAddrInst:
10761078
// switch_enum_addr does not produce any values. Subsequent uses of the address (unchecked_enum_data_addr)
10771079
// directly use the original address.

SwiftCompilerSources/Sources/Optimizer/Utilities/LocalVariableUtils.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,13 @@ extension LocalVariableAccessWalker: AddressUseVisitor {
525525
// switch_enum_addr is truly a leaf address use. It does not produce a new value. But in every other respect it is
526526
// like a load.
527527
visit(LocalVariableAccess(.load, operand))
528+
case let castBr as CheckedCastAddrBranchInst:
529+
if operand == castBr.sourceOperand {
530+
visit(LocalVariableAccess(.load, operand))
531+
} else {
532+
assert(operand == castBr.destinationOperand)
533+
visit(LocalVariableAccess(.store, operand))
534+
}
528535
case is DeallocStackInst:
529536
break
530537
default:

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,8 +2027,11 @@ final public class CheckedCastBranchInst : TermInst, UnaryInstruction {
20272027
}
20282028

20292029
final public class CheckedCastAddrBranchInst : TermInst {
2030-
public var source: Value { operands[0].value }
2031-
public var destination: Value { operands[1].value }
2030+
public var sourceOperand: Operand { return operands[0] }
2031+
public var destinationOperand: Operand { return operands[1] }
2032+
2033+
public var source: Value { sourceOperand.value }
2034+
public var destination: Value { destinationOperand.value }
20322035

20332036
public var sourceFormalType: CanonicalType {
20342037
CanonicalType(bridged: bridged.CheckedCastAddrBranch_getSourceFormalType())

test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,22 @@ extension MutableSpan {
429429
return false
430430
}
431431
}
432+
433+
// =============================================================================
434+
// Local variable analysis - address uses
435+
// =============================================================================
436+
437+
func dynamicCastGood<T>(_ span: Span<T>) {
438+
if let intSpan = span as? Span<Int> {
439+
_ = intSpan
440+
}
441+
}
442+
443+
@_lifetime(immortal)
444+
func dynamicCastBad<T>(_ span: Span<T>) -> Span<Int> {
445+
if let intSpan = span as? Span<Int> { // expected-error{{lifetime-dependent variable 'intSpan' escapes its scope}}
446+
// expected-note @-2{{it depends on the lifetime of argument 'span'}}
447+
return intSpan // expected-note{{this use causes the lifetime-dependent value to escape}}
448+
}
449+
return Span<Int>()
450+
}

0 commit comments

Comments
 (0)