Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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()) },
Expand Down
20 changes: 16 additions & 4 deletions tests/analysis/either.zig
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Loading