mirror of
https://github.com/apple/swift.git
synced 2026-10-22 19:15:50 +02:00
Add a mandatory `ImplicitDestroyChecker` pass, written in Swift, right after the move-only checker. Once the move-only checker has run, any legal transfer of a noncopyable value is a consume, and every other path ends with an explicit destroy, so the pass only needs to diagnose destroys of values that aren't implicitly destroyable outside of dead-end blocks. Destroys that only destroy stored properties are fine when each of those can be destroyed implicitly, as after `discard self`, or before the move-only checker reinitializes a struct one stored property at a time.
59 lines
1.7 KiB
Swift
59 lines
1.7 KiB
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: split-file %s %t
|
|
// RUN: %target-swift-frontend -emit-module -enable-experimental-feature NondeinitableTypes -module-name DeinitableLib -o %t/DeinitableLib.swiftmodule %t/DeinitableLib.swift
|
|
// RUN: %target-swift-frontend -typecheck -verify -enable-experimental-feature NondeinitableTypes -I %t %t/Client.swift -verify-ignore-unrelated
|
|
|
|
// REQUIRES: swift_feature_NondeinitableTypes
|
|
|
|
//--- DeinitableLib.swift
|
|
|
|
@frozen
|
|
public struct ND: ~Copyable, ~Deinitable {
|
|
public init() {}
|
|
|
|
public consuming func finish() {
|
|
discard self
|
|
}
|
|
}
|
|
|
|
public func borrowNondeinitable<T: ~Copyable & ~Deinitable>(_ t: borrowing T) {}
|
|
|
|
public func borrowNoncopyable<T: ~Copyable>(_ t: borrowing T) {}
|
|
|
|
public struct Box<T: ~Copyable & ~Deinitable>: ~Copyable, ~Deinitable {
|
|
public let value: T
|
|
}
|
|
|
|
public protocol HasNondeinitable {
|
|
associatedtype A: ~Copyable, ~Deinitable
|
|
}
|
|
|
|
public protocol HasNoncopyable {
|
|
associatedtype A: ~Copyable
|
|
}
|
|
|
|
//--- Client.swift
|
|
|
|
import DeinitableLib
|
|
|
|
// `~Deinitable` survives serialization on a nominal type, a generic parameter,
|
|
// and an associated type.
|
|
func test(_ nd: borrowing ND) {
|
|
borrowNondeinitable(nd) // Ok
|
|
borrowNoncopyable(nd) // expected-error {{global function 'borrowNoncopyable' requires that 'ND' conform to 'Deinitable'}}
|
|
}
|
|
|
|
func box(_: borrowing Box<ND>) {} // Ok
|
|
|
|
struct ConformsWithNondeinitable: HasNondeinitable { // Ok
|
|
typealias A = ND
|
|
}
|
|
|
|
func associatedTypes<T: HasNondeinitable, U: HasNoncopyable>(
|
|
_: T.Type, _ t: borrowing T.A, _: U.Type, _ u: borrowing U.A
|
|
) {
|
|
borrowNondeinitable(t) // Ok
|
|
borrowNoncopyable(t) // expected-error {{global function 'borrowNoncopyable' requires that 'T.A' conform to 'Deinitable'}}
|
|
borrowNoncopyable(u) // Ok
|
|
}
|