1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
// RUN: %target-typecheck-verify-swift -disable-availability-checking
enum Either<T,U> {
case first(T)
case second(U)
}
@resultBuilder
struct TupleBuilder {
static func buildBlock() -> () {
return ()
}
static func buildBlock<T1>(_ t1: T1) -> (T1) {
return (t1)
}
static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
return (t1, t2)
}
static func buildBlock<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3)
-> (T1, T2, T3) {
return (t1, t2, t3)
}
static func buildBlock<T1, T2, T3, T4>(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4)
-> (T1, T2, T3, T4) {
return (t1, t2, t3, t4)
}
static func buildBlock<T1, T2, T3, T4, T5>(
_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5
) -> (T1, T2, T3, T4, T5) {
return (t1, t2, t3, t4, t5)
}
static func buildDo<T>(_ value: T) -> T { return value }
static func buildIf<T>(_ value: T?) -> T? { return value }
static func buildEither<T,U>(first value: T) -> Either<T,U> {
return .first(value)
}
static func buildEither<T,U>(second value: U) -> Either<T,U> {
return .second(value)
}
}
protocol Tupled {
associatedtype TupleType
@TupleBuilder var tuple: TupleType { get }
}
struct TupleMe: Tupled {
var condition: Bool
// Okay: applies the result builder @TupleBuilder.
var tuple: some Any {
"hello"
if condition {
"nested"
}
3.14159
"world"
}
}
// Witness is separated from the context declaring conformance, so don't infer
// the result builder.
struct DoNotTupleMe {
var condition: Bool
var tuple: some Any { // expected-error{{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
"hello" // expected-warning{{string literal is unused}}
"world" // expected-warning{{string literal is unused}}
// expected-note@-1 {{did you mean to return the last expression?}} {{5-5=return }}
}
}
extension DoNotTupleMe: Tupled { }
@resultBuilder
struct OtherTupleBuilder {
static func buildBlock() -> () {
return ()
}
static func buildBlock<T1>(_ t1: T1) -> (T1) {
return (t1)
}
static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
return (t1, t2)
}
static func buildBlock<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3)
-> (T1, T2, T3) {
return (t1, t2, t3)
}
static func buildBlock<T1, T2, T3, T4>(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4)
-> (T1, T2, T3, T4) {
return (t1, t2, t3, t4)
}
static func buildBlock<T1, T2, T3, T4, T5>(
_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5
) -> (T1, T2, T3, T4, T5) {
return (t1, t2, t3, t4, t5)
}
static func buildDo<T>(_ value: T) -> T { return value }
static func buildIf<T>(_ value: T?) -> T? { return value }
static func buildEither<T,U>(first value: T) -> Either<T,U> {
return .first(value)
}
static func buildEither<T,U>(second value: U) -> Either<T,U> {
return .second(value)
}
}
protocol Tupled2 {
associatedtype TupleType
@TupleBuilder var tuple: TupleType { get }
}
struct TupleMe2: Tupled, Tupled2 {
var condition: Bool
// Okay: applies the result builder @TupleBuilder, even though it satisfies
// two requirements. (They have the same result builder)
var tuple: some Any {
"hello"
if condition {
"nested"
}
3.14159
"world"
}
}
protocol OtherTupled {
associatedtype OtherTupleType
@OtherTupleBuilder var tuple: OtherTupleType { get }
}
struct AmbigTupleMe: Tupled, OtherTupled {
var condition: Bool
// Ambiguous
// expected-note@+4{{add an explicit 'return' statement to not use a result builder}}{{+3:3-3=return <#expr#>\n}}
// expected-note@+3{{apply result builder 'TupleBuilder' (inferred from protocol 'Tupled')}}{{-1:3-3=@TupleBuilder }}
// expected-note@+2{{apply result builder 'OtherTupleBuilder' (inferred from protocol 'OtherTupled')}}{{-1:3-3=@OtherTupleBuilder }}
internal
var tuple: Void { // expected-error{{ambiguous result builder inferred for 'tuple': 'TupleBuilder' or 'OtherTupleBuilder'}}
"hello" // expected-warning{{string literal is unused}}
"world" // expected-warning{{string literal is unused}}
}
}
// Separating the conformances resolves the ambiguity.
struct TupleMeResolvedSeparate: Tupled {
var condition: Bool
var tuple: some Any {
"hello"
if condition {
"nested"
}
3.14159
"world"
}
}
extension TupleMeResolvedSeparate: OtherTupled { }
struct TupleMeResolvedExplicit: Tupled, OtherTupled {
var condition: Bool
var tuple: some Any {
return "hello"
}
}
// Inference through dynamic replacement
struct DynamicTupled: Tupled {
dynamic var tuple: some Any {
return "hello"
}
}
extension DynamicTupled {
@_dynamicReplacement(for: tuple)
var replacementTuple: some Any {
1
3.14159
"hello"
}
}
struct DynamicTupled2: Tupled, OtherTupled {
dynamic var tuple: some Any {
return "hello"
}
}
extension DynamicTupled2 {
@_dynamicReplacement(for: tuple)
var replacementTuple: some Any { // expected-error{{ambiguous result builder inferred for 'replacementTuple': 'TupleBuilder' or 'OtherTupleBuilder'}}
// expected-note@-1{{add an explicit 'return' statement to not use a result builder}}
// expected-note@-2{{apply result builder 'TupleBuilder' (inferred from protocol 'Tupled')}}
// expected-note@-3{{apply result builder 'OtherTupleBuilder' (inferred from protocol 'OtherTupled')}}
1
}
}
struct DynamicTupled3 {
@TupleBuilder dynamic var dynamicTuple: some Any {
0
}
}
extension DynamicTupled3: OtherTupled {
@_dynamicReplacement(for: dynamicTuple)
var tuple: some Any { // expected-error{{ambiguous result builder inferred for 'tuple': 'OtherTupleBuilder' or 'TupleBuilder'}}
// expected-note@-1{{add an explicit 'return' statement to not use a result builder}}
// expected-note@-2{{apply result builder 'OtherTupleBuilder' (inferred from protocol 'OtherTupled')}}
// expected-note@-3{{apply result builder 'TupleBuilder' (inferred from dynamic replacement of 'dynamicTuple')}}
0
}
}
|