| ... | @@ -18279,146 +18279,126 @@ fn resolvePeerTypes( | ... | @@ -18279,146 +18279,126 @@ fn resolvePeerTypes( |
| 18279 | }, | 18279 | }, |
| 18280 | }, | 18280 | }, |
| 18281 | .Pointer => { | 18281 | .Pointer => { |
| 18282 | if (candidate_ty.ptrSize() == .C) { | 18282 | const cand_info = candidate_ty.ptrInfo().data; |
| 18283 | // *T to [*c]T | 18283 | switch (chosen_ty_tag) { |
| 18284 | if (chosen_ty_tag == .Pointer) { | 18284 | .Pointer => { |
| 18285 | const chosen_elem_ty = chosen_ty.childType(); | 18285 | const chosen_info = chosen_ty.ptrInfo().data; |
| 18286 | const candidate_elem_ty = candidate_ty.childType(); | 18286 | |
| 18287 | if ((try sema.coerceInMemoryAllowed(block, chosen_elem_ty, candidate_elem_ty, false, target, src, src)) == .ok) { | 18287 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; |
| | 18288 | |
| | 18289 | // *[N]T to [*]T |
| | 18290 | // *[N]T to []T |
| | 18291 | if ((cand_info.size == .Many or cand_info.size == .Slice) and |
| | 18292 | chosen_info.size == .One and |
| | 18293 | chosen_info.pointee_type.zigTypeTag() == .Array) |
| | 18294 | { |
| | 18295 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` |
| | 18296 | convert_to_slice = false; |
| 18288 | chosen = candidate; | 18297 | chosen = candidate; |
| 18289 | chosen_i = candidate_i + 1; | 18298 | chosen_i = candidate_i + 1; |
| 18290 | continue; | 18299 | continue; |
| 18291 | } | 18300 | } |
| 18292 | } | 18301 | if (cand_info.size == .One and |
| 18293 | | 18302 | cand_info.pointee_type.zigTypeTag() == .Array and |
| 18294 | if (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt) { | 18303 | (chosen_info.size == .Many or chosen_info.size == .Slice)) |
| 18295 | chosen = candidate; | 18304 | { |
| 18296 | chosen_i = candidate_i + 1; | 18305 | // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T` |
| 18297 | continue; | 18306 | convert_to_slice = false; |
| 18298 | } | 18307 | continue; |
| 18299 | if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() != .Slice) { | 18308 | } |
| 18300 | continue; | | |
| 18301 | } | | |
| 18302 | } | | |
| 18303 | | | |
| 18304 | // [*c]T and *T | | |
| 18305 | if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() == .C) { | | |
| 18306 | const chosen_elem_ty = chosen_ty.childType(); | | |
| 18307 | const candidate_elem_ty = candidate_ty.childType(); | | |
| 18308 | if ((try sema.coerceInMemoryAllowed(block, chosen_elem_ty, candidate_elem_ty, false, target, src, src)) == .ok) { | | |
| 18309 | continue; | | |
| 18310 | } | | |
| 18311 | } | | |
| 18312 | | | |
| 18313 | // *[N]T to [*]T | | |
| 18314 | if (candidate_ty.ptrSize() == .Many and | | |
| 18315 | chosen_ty_tag == .Pointer and | | |
| 18316 | chosen_ty.ptrSize() == .One and | | |
| 18317 | chosen_ty.childType().zigTypeTag() == .Array) | | |
| 18318 | { | | |
| 18319 | chosen = candidate; | | |
| 18320 | chosen_i = candidate_i + 1; | | |
| 18321 | | | |
| 18322 | convert_to_slice = false; | | |
| 18323 | | | |
| 18324 | if (chosen_ty.isConstPtr() and !candidate_ty.isConstPtr()) | | |
| 18325 | seen_const = true; | | |
| 18326 | | | |
| 18327 | continue; | | |
| 18328 | } | | |
| 18329 | | | |
| 18330 | // *[N]T to [*]T (prev is many pointer) | | |
| 18331 | if (candidate_ty.ptrSize() == .One and | | |
| 18332 | candidate_ty.childType().zigTypeTag() == .Array and | | |
| 18333 | chosen_ty_tag == .Pointer and | | |
| 18334 | chosen_ty.ptrSize() == .Many) | | |
| 18335 | { | | |
| 18336 | if (candidate_ty.isConstPtr() and !chosen_ty.isConstPtr()) | | |
| 18337 | seen_const = true; | | |
| 18338 | | | |
| 18339 | continue; | | |
| 18340 | } | | |
| 18341 | | | |
| 18342 | // *[N]T to []T (prev is slice) | | |
| 18343 | // *[N]T to E![]T | | |
| 18344 | if ((chosen_ty.isSlice() or (chosen_ty_tag == .ErrorUnion and chosen_ty.errorUnionPayload().isSlice())) and | | |
| 18345 | candidate_ty.ptrSize() == .One and | | |
| 18346 | candidate_ty.childType().zigTypeTag() == .Array) | | |
| 18347 | { | | |
| 18348 | const chosen_elem_ty = switch (chosen_ty_tag) { | | |
| 18349 | .ErrorUnion => chosen_ty.errorUnionPayload().elemType2(), | | |
| 18350 | else => chosen_ty.elemType2(), | | |
| 18351 | }; | | |
| 18352 | const candidate_elem_ty = candidate_ty.childType().elemType2(); | | |
| 18353 | if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) { | | |
| 18354 | convert_to_slice = false; // it already is a slice | | |
| 18355 | | | |
| 18356 | // If the pointer is const then we need to const | | |
| 18357 | if (candidate_ty.isConstPtr()) | | |
| 18358 | seen_const = true; | | |
| 18359 | | | |
| 18360 | continue; | | |
| 18361 | } | | |
| 18362 | } | | |
| 18363 | | 18309 | |
| 18364 | // *[N]T to []T (current is slice) | 18310 | // *[N]T and *[M]T |
| 18365 | if (chosen_ty_tag == .Pointer and | 18311 | // Verify both are single-pointers to arrays. |
| 18366 | chosen_ty.ptrSize() == .One and | 18312 | // Keep the one whose element type can be coerced into. |
| 18367 | chosen_ty.childType().zigTypeTag() == .Array and | 18313 | if (chosen_info.size == .One and |
| 18368 | candidate_ty.isSlice()) | 18314 | cand_info.size == .One and |
| 18369 | { | 18315 | chosen_info.pointee_type.zigTypeTag() == .Array and |
| 18370 | const chosen_child_ty = chosen_ty.childType(); | 18316 | cand_info.pointee_type.zigTypeTag() == .Array) |
| 18371 | const chosen_elem_ty = chosen_child_ty.elemType2(); | 18317 | { |
| 18372 | const candidate_elem_ty = candidate_ty.elemType2(); | 18318 | const chosen_elem_ty = chosen_info.pointee_type.childType(); |
| 18373 | if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) { | 18319 | const cand_elem_ty = cand_info.pointee_type.childType(); |
| 18374 | chosen = candidate; | | |
| 18375 | chosen_i = candidate_i + 1; | | |
| 18376 | | 18320 | |
| 18377 | convert_to_slice = false; // it already is a slice | 18321 | const chosen_ok = .ok == try sema.coerceInMemoryAllowed(block, chosen_elem_ty, cand_elem_ty, chosen_info.mutable, target, src, src); |
| | 18322 | if (chosen_ok) { |
| | 18323 | convert_to_slice = true; |
| | 18324 | continue; |
| | 18325 | } |
| 18378 | | 18326 | |
| 18379 | // If the prev pointer is const then we need to const | 18327 | const cand_ok = .ok == try sema.coerceInMemoryAllowed(block, cand_elem_ty, chosen_elem_ty, cand_info.mutable, target, src, src); |
| 18380 | if (chosen_ty.isConstPtr()) | 18328 | if (cand_ok) { |
| 18381 | seen_const = true; | 18329 | convert_to_slice = true; |
| | 18330 | chosen = candidate; |
| | 18331 | chosen_i = candidate_i + 1; |
| | 18332 | continue; |
| | 18333 | } |
| 18382 | | 18334 | |
| 18383 | continue; | 18335 | // They're both bad. Report error. |
| 18384 | } | 18336 | // In the future we probably want to use the |
| 18385 | } | 18337 | // coerceInMemoryAllowed error reporting mechanism, |
| | 18338 | // however, for now we just fall through for the |
| | 18339 | // "incompatible types" error below. |
| | 18340 | } |
| 18386 | | 18341 | |
| 18387 | // *[N]T and *[M]T | 18342 | // [*c]T and any other pointer size |
| 18388 | // verify both are pointers to known lengths | 18343 | // Whichever element type can coerce to the other one, is |
| 18389 | if (chosen_ty_tag == .Pointer and | 18344 | // the one we will keep. If they're both OK then we keep the |
| 18390 | chosen_ty.ptrSize() == .One and | 18345 | // C pointer since it matches both single and many pointers. |
| 18391 | candidate_ty.ptrSize() == .One) | 18346 | if (cand_info.size == .C or chosen_info.size == .C) { |
| 18392 | { | 18347 | const cand_ok = .ok == try sema.coerceInMemoryAllowed(block, cand_info.pointee_type, chosen_info.pointee_type, cand_info.mutable, target, src, src); |
| 18393 | // verify both pointers are two arrays | 18348 | const chosen_ok = .ok == try sema.coerceInMemoryAllowed(block, chosen_info.pointee_type, cand_info.pointee_type, chosen_info.mutable, target, src, src); |
| 18394 | const chosen_child_ty = chosen_ty.childType(); | 18349 | |
| 18395 | const candidate_child_ty = candidate_ty.childType(); | 18350 | if (cand_ok) { |
| 18396 | if (chosen_child_ty.zigTypeTag() == .Array and candidate_child_ty.zigTypeTag() == .Array) { | 18351 | if (chosen_ok) { |
| 18397 | // If we can cerce the element types, then we can do this. | 18352 | if (chosen_info.size == .C) { |
| 18398 | const chosen_elem_ty = chosen_child_ty.elemType2(); | 18353 | continue; |
| 18399 | const candidate_elem_ty = candidate_child_ty.elemType2(); | 18354 | } else { |
| 18400 | if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) { | 18355 | chosen = candidate; |
| 18401 | // If there is a sentinel, it must match | 18356 | chosen_i = candidate_i + 1; |
| 18402 | if (chosen_child_ty.sentinel()) |chosen_sentinel| { | | |
| 18403 | if (candidate_child_ty.sentinel()) |candidate_sentinel| { | | |
| 18404 | if (!chosen_sentinel.eql(candidate_sentinel, chosen_elem_ty)) | | |
| 18405 | continue; | 18357 | continue; |
| 18406 | } else continue; | 18358 | } |
| | 18359 | } else { |
| | 18360 | chosen = candidate; |
| | 18361 | chosen_i = candidate_i + 1; |
| | 18362 | continue; |
| | 18363 | } |
| | 18364 | } else { |
| | 18365 | if (chosen_ok) { |
| | 18366 | continue; |
| | 18367 | } else { |
| | 18368 | // They're both bad. Report error. |
| | 18369 | // In the future we probably want to use the |
| | 18370 | // coerceInMemoryAllowed error reporting mechanism, |
| | 18371 | // however, for now we just fall through for the |
| | 18372 | // "incompatible types" error below. |
| | 18373 | } |
| 18407 | } | 18374 | } |
| 18408 | | 18375 | } |
| | 18376 | }, |
| | 18377 | .Int, .ComptimeInt => { |
| | 18378 | if (cand_info.size == .C) { |
| 18409 | chosen = candidate; | 18379 | chosen = candidate; |
| 18410 | chosen_i = candidate_i + 1; | 18380 | chosen_i = candidate_i + 1; |
| 18411 | | | |
| 18412 | convert_to_slice = true; | | |
| 18413 | | | |
| 18414 | // If one of the pointers is to const data, the slice | | |
| 18415 | // must also be const. | | |
| 18416 | if (candidate_child_ty.isConstPtr() or chosen_child_ty.isConstPtr()) | | |
| 18417 | seen_const = true; | | |
| 18418 | | | |
| 18419 | continue; | 18381 | continue; |
| 18420 | } | 18382 | } |
| 18421 | } | 18383 | }, |
| | 18384 | .ErrorUnion => { |
| | 18385 | const chosen_ptr_ty = chosen_ty.errorUnionPayload(); |
| | 18386 | if (chosen_ptr_ty.zigTypeTag() == .Pointer) { |
| | 18387 | const chosen_info = chosen_ptr_ty.ptrInfo().data; |
| | 18388 | |
| | 18389 | seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable; |
| | 18390 | |
| | 18391 | // *[N]T to E![*]T |
| | 18392 | // *[N]T to E![]T |
| | 18393 | if (cand_info.size == .One and |
| | 18394 | cand_info.pointee_type.zigTypeTag() == .Array and |
| | 18395 | (chosen_info.size == .Many or chosen_info.size == .Slice)) |
| | 18396 | { |
| | 18397 | continue; |
| | 18398 | } |
| | 18399 | } |
| | 18400 | }, |
| | 18401 | else => {}, |
| 18422 | } | 18402 | } |
| 18423 | }, | 18403 | }, |
| 18424 | .Optional => { | 18404 | .Optional => { |
| ... | @@ -18512,20 +18492,13 @@ fn resolvePeerTypes( | ... | @@ -18512,20 +18492,13 @@ fn resolvePeerTypes( |
| 18512 | | 18492 | |
| 18513 | const chosen_ty = sema.typeOf(chosen); | 18493 | const chosen_ty = sema.typeOf(chosen); |
| 18514 | | 18494 | |
| 18515 | if (any_are_null) { | | |
| 18516 | switch (chosen_ty.zigTypeTag()) { | | |
| 18517 | .Null, .Optional => return chosen_ty, | | |
| 18518 | else => return Type.optional(sema.arena, chosen_ty), | | |
| 18519 | } | | |
| 18520 | } | | |
| 18521 | | | |
| 18522 | if (convert_to_slice) { | 18495 | if (convert_to_slice) { |
| 18523 | // turn *[N]T => []T | 18496 | // turn *[N]T => []T |
| 18524 | const chosen_child_ty = chosen_ty.childType(); | 18497 | const chosen_child_ty = chosen_ty.childType(); |
| 18525 | var info = chosen_ty.ptrInfo(); | 18498 | var info = chosen_ty.ptrInfo(); |
| 18526 | info.data.sentinel = chosen_child_ty.sentinel(); | 18499 | info.data.sentinel = chosen_child_ty.sentinel(); |
| 18527 | info.data.size = .Slice; | 18500 | info.data.size = .Slice; |
| 18528 | info.data.mutable = seen_const or chosen_child_ty.isConstPtr(); | 18501 | info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr()); |
| 18529 | info.data.pointee_type = switch (chosen_child_ty.tag()) { | 18502 | info.data.pointee_type = switch (chosen_child_ty.tag()) { |
| 18530 | .array => chosen_child_ty.elemType2(), | 18503 | .array => chosen_child_ty.elemType2(), |
| 18531 | .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8), | 18504 | .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8), |
| ... | @@ -18533,8 +18506,12 @@ fn resolvePeerTypes( | ... | @@ -18533,8 +18506,12 @@ fn resolvePeerTypes( |
| 18533 | }; | 18506 | }; |
| 18534 | | 18507 | |
| 18535 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | 18508 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); |
| 18536 | const set_ty = err_set_ty orelse return new_ptr_ty; | 18509 | const opt_ptr_ty = if (any_are_null) |
| 18537 | return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty); | 18510 | try Type.optional(sema.arena, new_ptr_ty) |
| | 18511 | else |
| | 18512 | new_ptr_ty; |
| | 18513 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| | 18514 | return try Module.errorUnionType(sema.arena, set_ty, opt_ptr_ty); |
| 18538 | } | 18515 | } |
| 18539 | | 18516 | |
| 18540 | if (seen_const) { | 18517 | if (seen_const) { |
| ... | @@ -18545,20 +18522,37 @@ fn resolvePeerTypes( | ... | @@ -18545,20 +18522,37 @@ fn resolvePeerTypes( |
| 18545 | var info = ptr_ty.ptrInfo(); | 18522 | var info = ptr_ty.ptrInfo(); |
| 18546 | info.data.mutable = false; | 18523 | info.data.mutable = false; |
| 18547 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | 18524 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); |
| | 18525 | const opt_ptr_ty = if (any_are_null) |
| | 18526 | try Type.optional(sema.arena, new_ptr_ty) |
| | 18527 | else |
| | 18528 | new_ptr_ty; |
| 18548 | const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(); | 18529 | const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(); |
| 18549 | return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty); | 18530 | return try Module.errorUnionType(sema.arena, set_ty, opt_ptr_ty); |
| 18550 | }, | 18531 | }, |
| 18551 | .Pointer => { | 18532 | .Pointer => { |
| 18552 | var info = chosen_ty.ptrInfo(); | 18533 | var info = chosen_ty.ptrInfo(); |
| 18553 | info.data.mutable = false; | 18534 | info.data.mutable = false; |
| 18554 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | 18535 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); |
| 18555 | const set_ty = err_set_ty orelse return new_ptr_ty; | 18536 | const opt_ptr_ty = if (any_are_null) |
| 18556 | return try Module.errorUnionType(sema.arena, set_ty, new_ptr_ty); | 18537 | try Type.optional(sema.arena, new_ptr_ty) |
| | 18538 | else |
| | 18539 | new_ptr_ty; |
| | 18540 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| | 18541 | return try Module.errorUnionType(sema.arena, set_ty, opt_ptr_ty); |
| 18557 | }, | 18542 | }, |
| 18558 | else => return chosen_ty, | 18543 | else => return chosen_ty, |
| 18559 | } | 18544 | } |
| 18560 | } | 18545 | } |
| 18561 | | 18546 | |
| | 18547 | if (any_are_null) { |
| | 18548 | const opt_ty = switch (chosen_ty.zigTypeTag()) { |
| | 18549 | .Null, .Optional => chosen_ty, |
| | 18550 | else => try Type.optional(sema.arena, chosen_ty), |
| | 18551 | }; |
| | 18552 | const set_ty = err_set_ty orelse return opt_ty; |
| | 18553 | return try Module.errorUnionType(sema.arena, set_ty, opt_ty); |
| | 18554 | } |
| | 18555 | |
| 18562 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) { | 18556 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) { |
| 18563 | .ErrorSet => return ty, | 18557 | .ErrorSet => return ty, |
| 18564 | .ErrorUnion => { | 18558 | .ErrorUnion => { |