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