| 1 | struct ReceiverPatternExpect[T] { |
| 2 | value T |
| 3 | } |
| 4 | |
| 5 | struct MixedReceiverPatternBox[T, U] { |
| 6 | direct T |
| 7 | items U |
| 8 | } |
| 9 | |
| 10 | type IntListExpect = ReceiverPatternExpect[[]int] |
| 11 | type StringIntMapExpect = ReceiverPatternExpect[map[string]int] |
| 12 | type MixedIntStringListBox = MixedReceiverPatternBox[int, []string] |
| 13 | |
| 14 | fn (e ReceiverPatternExpect[T]) broad_receiver_returns_value() T { |
| 15 | return e.value |
| 16 | } |
| 17 | |
| 18 | fn (e ReceiverPatternExpect[[]int]) concrete_array_receiver_returns_len() int { |
| 19 | return e.value.len |
| 20 | } |
| 21 | |
| 22 | fn (e ReceiverPatternExpect[[]int]) same_name_prefers_concrete_receiver() string { |
| 23 | return 'concrete' |
| 24 | } |
| 25 | |
| 26 | fn (e ReceiverPatternExpect[[]int]) same_name_with_method_generic_prefers_concrete_receiver[U](extra U) string { |
| 27 | return 'concrete' |
| 28 | } |
| 29 | |
| 30 | fn (e ReceiverPatternExpect[[]T]) dynamic_array_receiver_pattern_returns_first_or_value(value T) T { |
| 31 | if e.value.len == 0 { |
| 32 | return value |
| 33 | } |
| 34 | return e.value[0] |
| 35 | } |
| 36 | |
| 37 | fn (e ReceiverPatternExpect[[]T]) same_name_prefers_concrete_receiver() string { |
| 38 | return 'pattern' |
| 39 | } |
| 40 | |
| 41 | fn (e ReceiverPatternExpect[[]T]) same_name_with_method_generic_prefers_concrete_receiver[U](extra U) string { |
| 42 | return 'pattern' |
| 43 | } |
| 44 | |
| 45 | fn (e ReceiverPatternExpect[[]T]) dynamic_array_receiver_pattern_pairs_with_method_generic[U](value T, |
| 46 | extra U) (T, U) { |
| 47 | if e.value.len == 0 { |
| 48 | return value, extra |
| 49 | } |
| 50 | return e.value[0], extra |
| 51 | } |
| 52 | |
| 53 | fn (e ReceiverPatternExpect[map[K]V]) map_receiver_pattern_returns_existing_or_default(key K, |
| 54 | value V) V { |
| 55 | if key in e.value { |
| 56 | return e.value[key] |
| 57 | } |
| 58 | return value |
| 59 | } |
| 60 | |
| 61 | fn (e ReceiverPatternExpect[map[K]V]) map_receiver_pattern_pairs_with_method_generic[U](key K, |
| 62 | value V, extra U) (V, U) { |
| 63 | if key in e.value { |
| 64 | return e.value[key], extra |
| 65 | } |
| 66 | return value, extra |
| 67 | } |
| 68 | |
| 69 | fn (e ReceiverPatternExpect[map[K]V]) same_name_map_exact_prefers_concrete[U](extra U) string { |
| 70 | _ = extra |
| 71 | return 'pattern' |
| 72 | } |
| 73 | |
| 74 | fn (e ReceiverPatternExpect[map[string]int]) same_name_map_exact_prefers_concrete[U](extra U) string { |
| 75 | _ = extra |
| 76 | return 'concrete' |
| 77 | } |
| 78 | |
| 79 | fn (e ReceiverPatternExpect[map[K]V]) same_name_map_method() string { |
| 80 | return 'pattern' |
| 81 | } |
| 82 | |
| 83 | fn (e ReceiverPatternExpect[map[string]int]) same_name_map_method() string { |
| 84 | return 'concrete' |
| 85 | } |
| 86 | |
| 87 | fn (b MixedReceiverPatternBox[T, []U]) mixed_receiver_pattern_values_with_method_generic[V](fallback U, |
| 88 | marker V) (T, U, V) { |
| 89 | if b.items.len == 0 { |
| 90 | return b.direct, fallback, marker |
| 91 | } |
| 92 | return b.direct, b.items[0], marker |
| 93 | } |
| 94 | |
| 95 | fn (b MixedReceiverPatternBox[int, []string]) same_name_with_method_generic_prefers_concrete_mixed_receiver[V](marker V) string { |
| 96 | return 'concrete' |
| 97 | } |
| 98 | |
| 99 | fn (b MixedReceiverPatternBox[T, []U]) same_name_with_method_generic_prefers_concrete_mixed_receiver[V](marker V) string { |
| 100 | return 'pattern' |
| 101 | } |
| 102 | |
| 103 | fn test_existing_generic_receiver_declarations_still_work() { |
| 104 | assert ReceiverPatternExpect[int]{ |
| 105 | value: 7 |
| 106 | }.broad_receiver_returns_value() == 7 |
| 107 | assert ReceiverPatternExpect[[]int]{ |
| 108 | value: [1, 2, 3] |
| 109 | }.concrete_array_receiver_returns_len() == 3 |
| 110 | } |
| 111 | |
| 112 | fn test_concrete_receiver_method_takes_precedence_over_structured_pattern() { |
| 113 | assert ReceiverPatternExpect[[]int]{ |
| 114 | value: [1, 2, 3] |
| 115 | }.same_name_prefers_concrete_receiver() == 'concrete' |
| 116 | assert ReceiverPatternExpect[[]string]{ |
| 117 | value: ['alpha'] |
| 118 | }.same_name_prefers_concrete_receiver() == 'pattern' |
| 119 | } |
| 120 | |
| 121 | fn test_concrete_receiver_method_with_method_generic_takes_precedence_over_structured_pattern() { |
| 122 | assert ReceiverPatternExpect[[]int]{ |
| 123 | value: [1, 2, 3] |
| 124 | }.same_name_with_method_generic_prefers_concrete_receiver('extra') == 'concrete' |
| 125 | assert ReceiverPatternExpect[[]int]{ |
| 126 | value: [1] |
| 127 | }.same_name_with_method_generic_prefers_concrete_receiver[string]('extra') == 'concrete' |
| 128 | assert ReceiverPatternExpect[[]string]{ |
| 129 | value: ['alpha'] |
| 130 | }.same_name_with_method_generic_prefers_concrete_receiver('extra') == 'pattern' |
| 131 | } |
| 132 | |
| 133 | fn test_structured_generic_receiver_patterns_can_be_declared() { |
| 134 | assert true |
| 135 | } |
| 136 | |
| 137 | fn test_dynamic_array_receiver_pattern_binds_element_type() { |
| 138 | assert ReceiverPatternExpect[[]int]{ |
| 139 | value: [1, 2, 3] |
| 140 | }.dynamic_array_receiver_pattern_returns_first_or_value(9) == 1 |
| 141 | assert ReceiverPatternExpect[[]string]{ |
| 142 | value: ['alpha', 'beta'] |
| 143 | }.dynamic_array_receiver_pattern_returns_first_or_value('fallback') == 'alpha' |
| 144 | } |
| 145 | |
| 146 | fn test_dynamic_array_receiver_pattern_binds_nested_element_type() { |
| 147 | assert ReceiverPatternExpect[[][]int]{ |
| 148 | value: [[1, 2], [3, 4]] |
| 149 | }.dynamic_array_receiver_pattern_returns_first_or_value([9, 10]) == [1, 2] |
| 150 | assert ReceiverPatternExpect[[]map[string]int]{ |
| 151 | value: [ |
| 152 | { |
| 153 | 'one': 1 |
| 154 | }, |
| 155 | ] |
| 156 | }.dynamic_array_receiver_pattern_returns_first_or_value({ |
| 157 | 'zero': 0 |
| 158 | })['one'] == 1 |
| 159 | } |
| 160 | |
| 161 | fn test_dynamic_array_receiver_pattern_method_generic_is_inferred() { |
| 162 | value, extra := ReceiverPatternExpect[[]int]{ |
| 163 | value: [1, 2, 3] |
| 164 | }.dynamic_array_receiver_pattern_pairs_with_method_generic(9, 'extra') |
| 165 | assert value == 1 |
| 166 | assert extra == 'extra' |
| 167 | explicit_value, explicit_extra := ReceiverPatternExpect[[]int]{ |
| 168 | value: [1, 2, 3] |
| 169 | }.dynamic_array_receiver_pattern_pairs_with_method_generic[string](9, 'explicit') |
| 170 | assert explicit_value == 1 |
| 171 | assert explicit_extra == 'explicit' |
| 172 | } |
| 173 | |
| 174 | fn test_map_receiver_pattern_binds_key_and_value_types() { |
| 175 | assert ReceiverPatternExpect[map[string]int]{ |
| 176 | value: { |
| 177 | 'one': 1 |
| 178 | } |
| 179 | }.map_receiver_pattern_returns_existing_or_default('one', 0) == 1 |
| 180 | assert ReceiverPatternExpect[map[int]string]{ |
| 181 | value: { |
| 182 | 2: 'two' |
| 183 | } |
| 184 | }.map_receiver_pattern_returns_existing_or_default(3, 'fallback') == 'fallback' |
| 185 | } |
| 186 | |
| 187 | fn test_map_receiver_pattern_method_generic_can_be_explicit() { |
| 188 | value, extra := ReceiverPatternExpect[map[string]int]{ |
| 189 | value: { |
| 190 | 'one': 1 |
| 191 | } |
| 192 | }.map_receiver_pattern_pairs_with_method_generic[string]('missing', 7, 'extra') |
| 193 | assert value == 7 |
| 194 | assert extra == 'extra' |
| 195 | } |
| 196 | |
| 197 | fn test_alias_to_array_receiver_pattern_binds_element_type() { |
| 198 | assert IntListExpect{ |
| 199 | value: [1, 2, 3] |
| 200 | }.dynamic_array_receiver_pattern_returns_first_or_value(9) == 1 |
| 201 | value, extra := IntListExpect{ |
| 202 | value: [1, 2, 3] |
| 203 | }.dynamic_array_receiver_pattern_pairs_with_method_generic[string](9, 'alias') |
| 204 | assert value == 1 |
| 205 | assert extra == 'alias' |
| 206 | inferred_value, inferred_extra := IntListExpect{ |
| 207 | value: [1, 2, 3] |
| 208 | }.dynamic_array_receiver_pattern_pairs_with_method_generic(9, 'inferred') |
| 209 | assert inferred_value == 1 |
| 210 | assert inferred_extra == 'inferred' |
| 211 | } |
| 212 | |
| 213 | fn test_alias_to_map_receiver_pattern_binds_key_and_value_types() { |
| 214 | assert StringIntMapExpect{ |
| 215 | value: { |
| 216 | 'one': 1 |
| 217 | } |
| 218 | }.map_receiver_pattern_returns_existing_or_default('one', 0) == 1 |
| 219 | value, extra := StringIntMapExpect{ |
| 220 | value: { |
| 221 | 'one': 1 |
| 222 | } |
| 223 | }.map_receiver_pattern_pairs_with_method_generic[bool]('missing', 7, true) |
| 224 | assert value == 7 |
| 225 | assert extra |
| 226 | } |
| 227 | |
| 228 | fn test_alias_to_map_exact_generic_method_takes_precedence_over_structured_pattern() { |
| 229 | assert StringIntMapExpect{ |
| 230 | value: { |
| 231 | 'one': 1 |
| 232 | } |
| 233 | }.same_name_map_exact_prefers_concrete('alias') == 'concrete' |
| 234 | } |
| 235 | |
| 236 | fn test_alias_to_map_exact_method_takes_precedence_over_structured_pattern() { |
| 237 | assert StringIntMapExpect{ |
| 238 | value: { |
| 239 | 'one': 1 |
| 240 | } |
| 241 | }.same_name_map_method() == 'concrete' |
| 242 | } |
| 243 | |
| 244 | fn test_alias_receiver_exact_method_takes_precedence_over_structured_pattern() { |
| 245 | assert IntListExpect{ |
| 246 | value: [1, 2, 3] |
| 247 | }.same_name_prefers_concrete_receiver() == 'concrete' |
| 248 | assert IntListExpect{ |
| 249 | value: [1] |
| 250 | }.same_name_with_method_generic_prefers_concrete_receiver[string]('extra') == 'concrete' |
| 251 | } |
| 252 | |
| 253 | fn test_mixed_direct_and_structured_receiver_pattern_method_generic() { |
| 254 | direct, item, marker := MixedReceiverPatternBox[int, []string]{ |
| 255 | direct: 7 |
| 256 | items: ['alpha'] |
| 257 | }.mixed_receiver_pattern_values_with_method_generic[bool]('fallback', true) |
| 258 | assert direct == 7 |
| 259 | assert item == 'alpha' |
| 260 | assert marker |
| 261 | inferred_direct, inferred_item, inferred_marker := MixedReceiverPatternBox[int, []string]{ |
| 262 | direct: 9 |
| 263 | items: []string{} |
| 264 | }.mixed_receiver_pattern_values_with_method_generic('fallback', 1.5) |
| 265 | assert inferred_direct == 9 |
| 266 | assert inferred_item == 'fallback' |
| 267 | assert inferred_marker == 1.5 |
| 268 | } |
| 269 | |
| 270 | fn test_alias_to_mixed_receiver_pattern_binds_direct_and_structured_slots() { |
| 271 | direct, item, marker := MixedIntStringListBox{ |
| 272 | direct: 7 |
| 273 | items: ['alpha'] |
| 274 | }.mixed_receiver_pattern_values_with_method_generic[bool]('fallback', true) |
| 275 | assert direct == 7 |
| 276 | assert item == 'alpha' |
| 277 | assert marker |
| 278 | assert MixedIntStringListBox{ |
| 279 | direct: 1 |
| 280 | items: ['alpha'] |
| 281 | }.same_name_with_method_generic_prefers_concrete_mixed_receiver[bool](true) == 'concrete' |
| 282 | } |
| 283 | |
| 284 | fn test_exact_mixed_receiver_method_with_method_generic_takes_precedence_over_structured_pattern() { |
| 285 | assert MixedReceiverPatternBox[int, []string]{ |
| 286 | direct: 1 |
| 287 | items: ['alpha'] |
| 288 | }.same_name_with_method_generic_prefers_concrete_mixed_receiver[bool](true) == 'concrete' |
| 289 | assert MixedReceiverPatternBox[int, []bool]{ |
| 290 | direct: 1 |
| 291 | items: [true] |
| 292 | }.same_name_with_method_generic_prefers_concrete_mixed_receiver[string]('marker') == 'pattern' |
| 293 | } |
| 294 | |
| 295 | fn test_map_receiver_pattern_binds_nested_value_type() { |
| 296 | assert ReceiverPatternExpect[map[string]map[string]int]{ |
| 297 | value: { |
| 298 | 'outer': { |
| 299 | 'inner': 7 |
| 300 | } |
| 301 | } |
| 302 | }.map_receiver_pattern_returns_existing_or_default('outer', { |
| 303 | 'default': 0 |
| 304 | })['inner'] == 7 |
| 305 | } |
| 306 | |