mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
parameter attributes for closure parameters. For regular function parameters, these constraints will have already been generated and solved when computing the backing property wrapper type at the function declaration. If the solver also generates these constraints when type checking a function call, it leads to misleading diagnostics about an argument mismatch that will appear at the function declaration instead of the call-site.
240 lines
9.0 KiB
Swift
240 lines
9.0 KiB
Swift
// RUN: %target-typecheck-verify-swift -swift-version 5
|
|
|
|
@propertyWrapper
|
|
struct NonMutatingWrapper<T> {
|
|
var wrappedValue: T {
|
|
get { fatalError() }
|
|
nonmutating set { fatalError() }
|
|
}
|
|
|
|
init(wrappedValue: T) { fatalError() }
|
|
}
|
|
|
|
@propertyWrapper
|
|
struct MutatingWrapper<T> {
|
|
var wrappedValue: T {
|
|
mutating get { fatalError() }
|
|
}
|
|
|
|
init(wrappedValue: T) { fatalError() }
|
|
}
|
|
|
|
// expected-error@+1 {{property wrapper applied to parameter must have a nonmutating 'wrappedValue' getter}}
|
|
func testMutatingGetter(@MutatingWrapper value: Int) {}
|
|
|
|
// expected-error@+1 {{property wrapper applied to parameter must have a nonmutating 'wrappedValue' getter}}
|
|
func testComposedMutating(@MutatingWrapper @NonMutatingWrapper value: Int) {}
|
|
|
|
// okay
|
|
func testComposedNonMutating(@NonMutatingWrapper @MutatingWrapper value: Int) {}
|
|
|
|
@propertyWrapper
|
|
struct NoProjection<T> {
|
|
var wrappedValue: T
|
|
}
|
|
|
|
// expected-note@+1 {{property wrapper type 'NoProjection<String>' does not support initialization from a projected value}}
|
|
func takesNoProjectionWrapper(@NoProjection value: String) {}
|
|
|
|
func testNoProjection(message: String) {
|
|
takesNoProjectionWrapper(value: message) // okay
|
|
|
|
// expected-error@+1 {{cannot use property wrapper projection argument}}
|
|
takesNoProjectionWrapper($value: message)
|
|
|
|
// expected-error@+2 {{cannot use property wrapper projection parameter}}
|
|
// expected-note@+1 {{property wrapper type 'NoProjection<Int>' does not support initialization from a projected value}}
|
|
let _: (NoProjection<Int>) -> Int = { $value in
|
|
return value
|
|
}
|
|
}
|
|
|
|
struct Projection<T> {
|
|
var value: T
|
|
}
|
|
|
|
// expected-note@+2 {{generic struct 'Wrapper' is not '@usableFromInline' or public}}
|
|
@propertyWrapper
|
|
struct Wrapper<T> { // expected-note 3 {{type declared here}}
|
|
// expected-note@+1 {{initializer 'init(wrappedValue:)' is not '@usableFromInline' or public}}
|
|
init(wrappedValue: T) {
|
|
self.wrappedValue = wrappedValue
|
|
}
|
|
|
|
init(projectedValue: Projection<T>) {
|
|
self.wrappedValue = projectedValue.value
|
|
}
|
|
|
|
var wrappedValue: T
|
|
var projectedValue: Projection<T> { Projection(value: wrappedValue) }
|
|
}
|
|
|
|
// expected-note@+2 {{property wrapper has arguments in the wrapper attribute}}
|
|
// expected-note@+1 {{in call to function 'hasWrapperAttributeArg(value:)'}}
|
|
func hasWrapperAttributeArg<T>(@Wrapper() value: T) {}
|
|
|
|
func testWrapperAttributeArg(projection: Projection<Int>) {
|
|
hasWrapperAttributeArg(value: projection.value)
|
|
|
|
// expected-error@+2 {{cannot use property wrapper projection argument}}
|
|
// expected-error@+1 {{generic parameter 'T' could not be inferred}}
|
|
hasWrapperAttributeArg($value: projection)
|
|
}
|
|
|
|
struct S {
|
|
// expected-error@+1 {{property wrapper attribute on parameter not yet supported on subscript}}
|
|
subscript(@Wrapper position: Int) -> Int { 0 }
|
|
}
|
|
|
|
func testInvalidArgLabel(projection: Projection<Int>) {
|
|
// expected-note@+1 2 {{parameter 'argLabel' does not have an attached property wrapper}}
|
|
func noWrappers(argLabel: Int) {}
|
|
|
|
// expected-error@+1 {{cannot use property wrapper projection argument}}
|
|
let ref = noWrappers($argLabel:)
|
|
|
|
// expected-error@+1 {{cannot use property wrapper projection argument}}
|
|
noWrappers($argLabel: 10)
|
|
|
|
func takesWrapper(@Wrapper argLabel: Int) {}
|
|
|
|
// expected-error@+1 {{cannot convert value of type 'Projection<Int>' to expected argument type 'Int'}}
|
|
takesWrapper(argLabel: projection)
|
|
}
|
|
|
|
protocol P {
|
|
// expected-error@+1 {{parameter 'arg' declared inside a protocol cannot have a wrapper}}
|
|
func requirement(@Wrapper arg: Int)
|
|
}
|
|
|
|
enum E {
|
|
// expected-error@+1 {{expected parameter name followed by ':'}}
|
|
case one(@Wrapper value: Int)
|
|
}
|
|
|
|
// expected-error@+1 {{function cannot be declared public because its parameter uses an internal API wrapper type}}
|
|
public func f1(@Wrapper value: Int) {}
|
|
|
|
// expected-error@+3 {{generic struct 'Wrapper' is internal and cannot be referenced from an '@inlinable' function}}
|
|
// expected-error@+2 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
|
|
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
|
|
@inlinable func f2(@Wrapper value: Int) {}
|
|
|
|
// expected-error@+1 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
|
|
@usableFromInline func f3(@Wrapper value: Int) {}
|
|
|
|
@available(*, unavailable)
|
|
@propertyWrapper
|
|
struct UnavailableWrapper<T> { // expected-note {{'UnavailableWrapper' has been explicitly marked unavailable here}}
|
|
var wrappedValue: T
|
|
}
|
|
|
|
// expected-error@+1 {{'UnavailableWrapper' is unavailable}}
|
|
func testUnavailableWrapper(@UnavailableWrapper value: Int) {}
|
|
|
|
@propertyWrapper
|
|
public struct PublicWrapper<T> {
|
|
public init(wrappedValue: T) { fatalError() }
|
|
public init(projectedValue: PublicWrapper<T>) { fatalError() }
|
|
public var wrappedValue: T
|
|
public var projectedValue: PublicWrapper<T> { self }
|
|
}
|
|
|
|
// expected-note@+2 2 {{generic struct 'InternalWrapper' is not '@usableFromInline' or public}}
|
|
@propertyWrapper
|
|
struct InternalWrapper<T> { // expected-note 3 {{type declared here}}
|
|
var wrappedValue: T
|
|
|
|
// expected-note@+1 2 {{initializer 'init(wrappedValue:)' is not '@usableFromInline' or public}}
|
|
init(wrappedValue: T) { self.wrappedValue = wrappedValue }
|
|
}
|
|
|
|
func testWrapperStorageMutability(@InternalWrapper value: Int) {
|
|
_ = _value
|
|
// expected-error@+1 {{cannot assign to value: '_value' is immutable}}
|
|
_value = InternalWrapper(wrappedValue: 10)
|
|
}
|
|
|
|
// expected-error@+1 {{function cannot be declared public because its parameter uses an internal API wrapper type}}
|
|
public func testComposition1(@PublicWrapper @InternalWrapper value: Int) {}
|
|
|
|
// Okay because `InternalWrapper` is implementation-detail.
|
|
public func testComposition2(@InternalWrapper @PublicWrapper value: Int) {}
|
|
|
|
// expected-error@+1 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
|
|
@usableFromInline func testComposition3(@PublicWrapper @InternalWrapper value: Int) {}
|
|
|
|
// Okay because `InternalWrapper` is implementation-detail.
|
|
@usableFromInline func testComposition4(@InternalWrapper @PublicWrapper value: Int) {}
|
|
|
|
// expected-error@+3 {{generic struct 'InternalWrapper' is internal and cannot be referenced from an '@inlinable' function}}
|
|
// expected-error@+2 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
|
|
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
|
|
@inlinable func testComposition5(@PublicWrapper @InternalWrapper value: Int) {}
|
|
|
|
// expected-error@+2 {{generic struct 'InternalWrapper' is internal and cannot be referenced from an '@inlinable' function}}
|
|
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
|
|
@inlinable func testComposition6(@InternalWrapper @PublicWrapper value: Int) {}
|
|
|
|
protocol Q {
|
|
associatedtype A
|
|
}
|
|
|
|
// expected-note@+1 {{where 'T' = 'Int'}}
|
|
func takesClosure<T: Q>(type: T.Type, _ closure: (T.A) -> Void) {}
|
|
|
|
func testMissingWrapperType() {
|
|
// expected-error@+1 {{global function 'takesClosure(type:_:)' requires that 'Int' conform to 'Q'}}
|
|
takesClosure(type: Int.self) { $value in
|
|
return
|
|
}
|
|
|
|
struct S: Q {
|
|
typealias A = (Int, Int)
|
|
}
|
|
|
|
// expected-error@+1 {{inferred projection type 'S.A' (aka '(Int, Int)') is not a property wrapper}}
|
|
takesClosure(type: S.self) { $value in
|
|
return
|
|
}
|
|
}
|
|
|
|
@propertyWrapper
|
|
struct OptionalWrapper<Value> { // expected-note {{'Value' declared as parameter to type 'OptionalWrapper'}}
|
|
var wrappedValue: Value?
|
|
var projectedValue: Self { self }
|
|
init(wrappedValue: Value?) { self.wrappedValue = wrappedValue }
|
|
init(projectedValue: Self) { self = projectedValue }
|
|
}
|
|
|
|
// expected-error@+2 {{generic parameter 'Value' could not be inferred}} expected-note@+2 {{}}
|
|
// expected-error@+1 {{property type 'Int' does not match 'wrappedValue' type 'Value?'}}
|
|
func testWrappedValueMismatch(@OptionalWrapper value: Int) {}
|
|
|
|
@propertyWrapper
|
|
struct ProjectionWrapper<Value> {
|
|
var wrappedValue: Value
|
|
var projectedValue: Self { self }
|
|
init(projectedValue: Self) { self = projectedValue }
|
|
}
|
|
|
|
func testInvalidWrapperInference() {
|
|
struct S<V> {
|
|
static func test(_ keyPath: KeyPath<V, String>) {} // expected-note {{'test' declared here}}
|
|
}
|
|
|
|
// expected-error@+1 {{trailing closure passed to parameter of type 'KeyPath<Int, String>' that does not accept a closure}}
|
|
S<Int>.test { $value in }
|
|
// expected-error@+1 {{cannot convert value of type '(_) -> ()' to expected argument type 'KeyPath<Int, String>'}}
|
|
S<Int>.test({ $value in })
|
|
|
|
func testGenericClosure<T>(_ closure: T) {}
|
|
// expected-error@+1 {{unable to infer type of a closure parameter '$value' in the current context}}
|
|
testGenericClosure { $value in }
|
|
testGenericClosure { ($value: ProjectionWrapper<Int>) in } // okay
|
|
|
|
func testExtraParameter(_ closure: () -> Void) {}
|
|
// expected-error@+1 {{contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body}}
|
|
testExtraParameter { $value in }
|
|
}
|