authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-02-22 19:43:10+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:12+00:00
log7bfe96fddcdc27db58a9a758b9e9aed2ed3370cc
tree4853428f5d1a537493e73e445ec4fbaf3ae9e9e9
parent5cc12da1c0b9e516e356d4d13c48ae671d2e17ff
signaturelock-open Commit is signed but in an unrecognized format.

frontend: fix bugs

did you know that if semantic analysis fails you should return error.AnalysisFail?

2 files changed, 18 insertions(+), 11 deletions(-)

src/Sema.zig+11-6
...@@ -23393,8 +23393,13 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -23393,8 +23393,13 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
23393 const field_name_src = block.builtinCallArgSrc(extra.src_node, 0);23393 const field_name_src = block.builtinCallArgSrc(extra.src_node, 0);
23394 const field_ptr_src = block.builtinCallArgSrc(extra.src_node, 1);23394 const field_ptr_src = block.builtinCallArgSrc(extra.src_node, 1);
2339523395
23396 const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr");23396 const maybe_opt_parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr");
23397 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);23397 try sema.checkPtrType(block, inst_src, maybe_opt_parent_ptr_ty, true);
23398 const parent_ptr_ty = switch (maybe_opt_parent_ptr_ty.zigTypeTag(zcu)) {
23399 .optional => maybe_opt_parent_ptr_ty.optionalChild(zcu),
23400 .pointer => maybe_opt_parent_ptr_ty,
23401 else => unreachable,
23402 };
23398 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);23403 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
23399 if (parent_ptr_info.flags.size != .one) {23404 if (parent_ptr_info.flags.size != .one) {
23400 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});23405 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});
...@@ -23441,7 +23446,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -23441,7 +23446,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
23441 );23446 );
2344223447
23443 const unaligned_parent_ptr_ty = try pt.ptrType(info: {23448 const unaligned_parent_ptr_ty = try pt.ptrType(info: {
23444 var info = parent_ptr_ty.ptrInfo(zcu);23449 var info = parent_ptr_info;
23445 info.flags.alignment = hypothetical_field_ptr_ty.ptrAlignment(zcu);23450 info.flags.alignment = hypothetical_field_ptr_ty.ptrAlignment(zcu);
23446 break :info info;23451 break :info info;
23447 });23452 });
...@@ -23512,7 +23517,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -23512,7 +23517,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
23512 // a field pointer of type `*align(1) u16`.23517 // a field pointer of type `*align(1) u16`.
23513 switch (hypothetical_field_ptr_ty.ptrAlignment(zcu).order(parent_ptr_ty.ptrAlignment(zcu))) {23518 switch (hypothetical_field_ptr_ty.ptrAlignment(zcu).order(parent_ptr_ty.ptrAlignment(zcu))) {
23514 .gt => unreachable, // getting a field pointer can never increase alignment23519 .gt => unreachable, // getting a field pointer can never increase alignment
23515 .eq => return unaligned_parent_ptr,23520 .eq => return sema.coerce(block, maybe_opt_parent_ptr_ty, unaligned_parent_ptr, inst_src),
23516 .lt => if (flags.align_cast) {23521 .lt => if (flags.align_cast) {
23517 // Go through `ptrCastFull` for the safety check.23522 // Go through `ptrCastFull` for the safety check.
23518 return sema.ptrCastFull(23523 return sema.ptrCastFull(
...@@ -23521,7 +23526,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -23521,7 +23526,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
23521 inst_src,23526 inst_src,
23522 unaligned_parent_ptr,23527 unaligned_parent_ptr,
23523 inst_src,23528 inst_src,
23524 parent_ptr_ty,23529 maybe_opt_parent_ptr_ty,
23525 "@fieldParentPtr",23530 "@fieldParentPtr",
23526 );23531 );
23527 } else return sema.failWithOwnedErrorMsg(block, msg: {23532 } else return sema.failWithOwnedErrorMsg(block, msg: {
...@@ -25184,7 +25189,7 @@ pub fn explainWhyTypeIsNotExtern(...@@ -25184,7 +25189,7 @@ pub fn explainWhyTypeIsNotExtern(
25184 }25189 }
25185 },25190 },
25186 .@"union" => {25191 .@"union" => {
25187 const union_obj = zcu.intern_pool.loadStructType(ty.toIntern());25192 const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern());
25188 switch (union_obj.layout) {25193 switch (union_obj.layout) {
25189 .auto => try sema.errNote(src_loc, msg, "union with automatic layout has no guaranteed in-memory representation", .{}),25194 .auto => try sema.errNote(src_loc, msg, "union with automatic layout has no guaranteed in-memory representation", .{}),
25190 .@"extern" => unreachable,25195 .@"extern" => unreachable,
src/Zcu/PerThread.zig+7-5
...@@ -1393,17 +1393,17 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1393,17 +1393,17 @@ pub fn ensureTypeLayoutUpToDate(
1393 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),1393 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),
1394 else => unreachable,1394 else => unreachable,
1395 };1395 };
1396 const new_success: bool = if (result) s: {1396 const new_failed: bool = if (result) failed: {
1397 break :s true;1397 break :failed false;
1398 } else |err| switch (err) {1398 } else |err| switch (err) {
1399 error.AnalysisFail => success: {1399 error.AnalysisFail => failed: {
1400 if (!zcu.failed_analysis.contains(anal_unit)) {1400 if (!zcu.failed_analysis.contains(anal_unit)) {
1401 // If this unit caused the error, it would have an entry in `failed_analysis`.1401 // If this unit caused the error, it would have an entry in `failed_analysis`.
1402 // Since it does not, this must be a transitive failure.1402 // Since it does not, this must be a transitive failure.
1403 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});1403 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1404 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});1404 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1405 }1405 }
1406 break :success false;1406 break :failed true;
1407 },1407 },
1408 error.OutOfMemory,1408 error.OutOfMemory,
1409 error.Canceled,1409 error.Canceled,
...@@ -1422,8 +1422,10 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1422,8 +1422,10 @@ pub fn ensureTypeLayoutUpToDate(
1422 comp.link_prog_node.increaseEstimatedTotalItems(1);1422 comp.link_prog_node.increaseEstimatedTotalItems(1);
1423 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{1423 try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{
1424 .ty = ty.toIntern(),1424 .ty = ty.toIntern(),
1425 .success = new_success,1425 .success = !new_failed,
1426 } });1426 } });
1427
1428 if (new_failed) return error.AnalysisFail;
1427}1429}
14281430
1429/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis1431/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis