| ... | ... | @@ -18279,146 +18279,126 @@ fn resolvePeerTypes( |
| 18279 | 18279 | }, |
| 18280 | 18280 | }, |
| 18281 | 18281 | .Pointer => { |
| 18282 | | if (candidate_ty.ptrSize() == .C) { |
| 18283 | | // *T to [*c]T |
| 18284 | | if (chosen_ty_tag == .Pointer) { |
| 18285 | | const chosen_elem_ty = chosen_ty.childType(); |
| 18286 | | const candidate_elem_ty = candidate_ty.childType(); |
| 18287 | | if ((try sema.coerceInMemoryAllowed(block, chosen_elem_ty, candidate_elem_ty, false, target, src, src)) == .ok) { |
| 18282 | const cand_info = candidate_ty.ptrInfo().data; |
| 18283 | switch (chosen_ty_tag) { |
| 18284 | .Pointer => { |
| 18285 | const chosen_info = chosen_ty.ptrInfo().data; |
| 18286 | |
| 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 | 18297 | chosen = candidate; |
| 18289 | 18298 | chosen_i = candidate_i + 1; |
| 18290 | 18299 | continue; |
| 18291 | 18300 | } |
| 18292 | | } |
| 18293 | | |
| 18294 | | if (chosen_ty_tag == .Int or chosen_ty_tag == .ComptimeInt) { |
| 18295 | | chosen = candidate; |
| 18296 | | chosen_i = candidate_i + 1; |
| 18297 | | continue; |
| 18298 | | } |
| 18299 | | if (chosen_ty_tag == .Pointer and chosen_ty.ptrSize() != .Slice) { |
| 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 | | } |
| 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 | } |
| 18363 | 18309 | |
| 18364 | | // *[N]T to []T (current is slice) |
| 18365 | | if (chosen_ty_tag == .Pointer and |
| 18366 | | chosen_ty.ptrSize() == .One and |
| 18367 | | chosen_ty.childType().zigTypeTag() == .Array and |
| 18368 | | candidate_ty.isSlice()) |
| 18369 | | { |
| 18370 | | const chosen_child_ty = chosen_ty.childType(); |
| 18371 | | const chosen_elem_ty = chosen_child_ty.elemType2(); |
| 18372 | | const candidate_elem_ty = candidate_ty.elemType2(); |
| 18373 | | if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) { |
| 18374 | | chosen = candidate; |
| 18375 | | 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(); |
| 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 |
| 18380 | | if (chosen_ty.isConstPtr()) |
| 18381 | | 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 | } |
| 18382 | 18334 | |
| 18383 | | continue; |
| 18384 | | } |
| 18385 | | } |
| 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 | } |
| 18386 | 18341 | |
| 18387 | | // *[N]T and *[M]T |
| 18388 | | // verify both are pointers to known lengths |
| 18389 | | if (chosen_ty_tag == .Pointer and |
| 18390 | | chosen_ty.ptrSize() == .One and |
| 18391 | | candidate_ty.ptrSize() == .One) |
| 18392 | | { |
| 18393 | | // verify both pointers are two arrays |
| 18394 | | const chosen_child_ty = chosen_ty.childType(); |
| 18395 | | const candidate_child_ty = candidate_ty.childType(); |
| 18396 | | if (chosen_child_ty.zigTypeTag() == .Array and candidate_child_ty.zigTypeTag() == .Array) { |
| 18397 | | // If we can cerce the element types, then we can do this. |
| 18398 | | const chosen_elem_ty = chosen_child_ty.elemType2(); |
| 18399 | | const candidate_elem_ty = candidate_child_ty.elemType2(); |
| 18400 | | if ((try sema.coerceInMemoryAllowed(block, candidate_elem_ty, chosen_elem_ty, false, target, src, src)) == .ok) { |
| 18401 | | // If there is a sentinel, it must match |
| 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)) |
| 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; |
| 18405 | 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 | 18379 | chosen = candidate; |
| 18410 | 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 | 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 | 18404 | .Optional => { |
| ... | ... | @@ -18512,20 +18492,13 @@ fn resolvePeerTypes( |
| 18512 | 18492 | |
| 18513 | 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 | 18495 | if (convert_to_slice) { |
| 18523 | 18496 | // turn *[N]T => []T |
| 18524 | 18497 | const chosen_child_ty = chosen_ty.childType(); |
| 18525 | 18498 | var info = chosen_ty.ptrInfo(); |
| 18526 | 18499 | info.data.sentinel = chosen_child_ty.sentinel(); |
| 18527 | 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 | 18502 | info.data.pointee_type = switch (chosen_child_ty.tag()) { |
| 18530 | 18503 | .array => chosen_child_ty.elemType2(), |
| 18531 | 18504 | .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8), |
| ... | ... | @@ -18533,8 +18506,12 @@ fn resolvePeerTypes( |
| 18533 | 18506 | }; |
| 18534 | 18507 | |
| 18535 | 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; |
| 18537 | | 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); |
| 18538 | 18515 | } |
| 18539 | 18516 | |
| 18540 | 18517 | if (seen_const) { |
| ... | ... | @@ -18545,20 +18522,37 @@ fn resolvePeerTypes( |
| 18545 | 18522 | var info = ptr_ty.ptrInfo(); |
| 18546 | 18523 | info.data.mutable = false; |
| 18547 | 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 | 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 | 18532 | .Pointer => { |
| 18552 | 18533 | var info = chosen_ty.ptrInfo(); |
| 18553 | 18534 | info.data.mutable = false; |
| 18554 | 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; |
| 18556 | | 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); |
| 18557 | 18542 | }, |
| 18558 | 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 | 18556 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) { |
| 18563 | 18557 | .ErrorSet => return ty, |
| 18564 | 18558 | .ErrorUnion => { |