diff --git a/src/analysis.zig b/src/analysis.zig index 227d8a16a..de98d7ba1 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -3918,29 +3918,39 @@ pub const Type = struct { var deduplicator: Deduplicator = .empty; defer deduplicator.deinit(arena); - const has_type_val = for (entries) |entry| { - if (entry.type.data == .compile_error) { - continue; - } - break entry.type.is_type_val; - } else entries[0].type.is_type_val; + var has_type_val: bool = false; + var has_useful_type: bool = false; + for (entries) |entry| { + if (entry.type.data == .compile_error) continue; + if (entry.type.data == .ip_index and entry.type.data.ip_index.type == .noreturn_type) continue; + if (entry.type.data == .ip_index and entry.type.data.ip_index.type == .undefined_type) continue; + + has_useful_type = true; + if (entry.type.is_type_val) has_type_val = true; + } for (entries) |entry| { + if (has_useful_type) { + if (entry.type.data == .compile_error) continue; + if (entry.type.data == .ip_index and entry.type.data.ip_index.type == .noreturn_type) continue; + if (entry.type.data == .ip_index and entry.type.data.ip_index.type == .undefined_type) continue; + } try deduplicator.put( arena, .{ .type_data = entry.type.data, .descriptor = entry.descriptor }, {}, ); - if (entry.type.data == .compile_error) { - continue; - } if (entry.type.is_type_val != has_type_val) { return null; } } - if (deduplicator.count() == 1) - return entries[0].type; + if (deduplicator.count() == 0) unreachable; + + if (deduplicator.count() == 1) return .{ + .data = deduplicator.keys()[0].type_data, + .is_type_val = has_type_val, + }; return .{ .data = .{ .either = try arena.dupe(Type.Data.EitherEntry, deduplicator.keys()) }, diff --git a/tests/analysis/either.zig b/tests/analysis/either.zig index 7969cae7a..c080cec24 100644 --- a/tests/analysis/either.zig +++ b/tests/analysis/either.zig @@ -1,17 +1,29 @@ const UnknownType: type = undefined; const unknown_value: UnknownType = undefined; -const non_type_and_type: if (true) undefined else i32 = unknown_value; +const non_type_and_type: if (true) 42 else i32 = unknown_value; // ^^^^^^^^^^^^^^^^^ (unknown)() -const type_and_non_type: if (true) i32 else undefined = unknown_value; +const type_and_non_type: if (true) i32 else 42 = unknown_value; // ^^^^^^^^^^^^^^^^^ (unknown)() +const undefined_and_type: if (true) undefined else i32 = @as(i32, 1); +// ^^^^^^^^^^^^^^^^^^ (i32)() + +const type_and_undefined: if (true) i32 else undefined = 1; +// ^^^^^^^^^^^^^^^^^^ (i32)() + +const unreachable_and_type: if (true) unreachable else i32 = @as(i32, 1); +// ^^^^^^^^^^^^^^^^^^^^ (i32)() + +const type_and_unreachable: if (true) i32 else unreachable = 1; +// ^^^^^^^^^^^^^^^^^^^^ (i32)() + const compile_error_and_type: if (true) @compileError("Foo") else i32 = 1; -// ^^^^^^^^^^^^^^^^^^^^^^ (either type)() +// ^^^^^^^^^^^^^^^^^^^^^^ (i32)() const type_and_compile_error: if (true) i32 else @compileError("Foo") = 1; -// ^^^^^^^^^^^^^^^^^^^^^^ (either type)() +// ^^^^^^^^^^^^^^^^^^^^^^ (i32)() const StructU32 = struct { field: u32 = 42,