Skip to content

Commit 9961621

Browse files
authored
Merge pull request #13497 from Vexu/stage2-fixes
Stage2 bug fixes
2 parents 8a58185 + 87cf278 commit 9961621

17 files changed

+329
-65
lines changed

src/AstGen.zig

Lines changed: 156 additions & 34 deletions
Large diffs are not rendered by default.

src/Autodoc.zig

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,15 @@ fn walkInstruction(
21292129
file,
21302130
parent_scope,
21312131
parent_src,
2132-
getBlockInlineBreak(file.zir, inst_index),
2132+
getBlockInlineBreak(file.zir, inst_index) orelse {
2133+
const res = DocData.WalkResult{ .expr = .{
2134+
.comptimeExpr = self.comptime_exprs.items.len,
2135+
} };
2136+
try self.comptime_exprs.append(self.arena, .{
2137+
.code = "if (...) { ... }",
2138+
});
2139+
return res;
2140+
},
21332141
need_type,
21342142
);
21352143
},
@@ -3155,7 +3163,7 @@ fn walkDecls(
31553163
2 => {
31563164
// decl test
31573165
const decl_being_tested = scope.resolveDeclName(doc_comment_index);
3158-
const func_index = getBlockInlineBreak(file.zir, value_index);
3166+
const func_index = getBlockInlineBreak(file.zir, value_index).?;
31593167

31603168
const pl_node = data[Zir.refToIndex(func_index).?].pl_node;
31613169
const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src);
@@ -4301,12 +4309,13 @@ fn walkRef(
43014309
}
43024310
}
43034311

4304-
fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref {
4312+
fn getBlockInlineBreak(zir: Zir, inst_index: usize) ?Zir.Inst.Ref {
43054313
const tags = zir.instructions.items(.tag);
43064314
const data = zir.instructions.items(.data);
43074315
const pl_node = data[inst_index].pl_node;
43084316
const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index);
43094317
const break_index = zir.extra[extra.end..][extra.data.body_len - 1];
4318+
if (tags[break_index] == .condbr_inline) return null;
43104319
std.debug.assert(tags[break_index] == .break_inline);
43114320
return data[break_index].@"break".operand;
43124321
}

src/Sema.zig

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,8 @@ fn analyzeBodyInner(
14911491
return err;
14921492
};
14931493
const inline_body = if (cond.val.toBool()) then_body else else_body;
1494+
1495+
try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src);
14941496
const old_runtime_index = block.runtime_index;
14951497
defer block.runtime_index = old_runtime_index;
14961498
const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
@@ -5658,14 +5660,14 @@ fn lookupInNamespace(
56585660
const src_file = block.namespace.file_scope;
56595661

56605662
const gpa = sema.gpa;
5661-
var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{};
5663+
var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};
56625664
defer checked_namespaces.deinit(gpa);
56635665

56645666
// Keep track of name conflicts for error notes.
56655667
var candidates: std.ArrayListUnmanaged(Decl.Index) = .{};
56665668
defer candidates.deinit(gpa);
56675669

5668-
try checked_namespaces.put(gpa, namespace, {});
5670+
try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file);
56695671
var check_i: usize = 0;
56705672

56715673
while (check_i < checked_namespaces.count()) : (check_i += 1) {
@@ -5674,7 +5676,7 @@ fn lookupInNamespace(
56745676
// Skip decls which are not marked pub, which are in a different
56755677
// file than the `a.b`/`@hasDecl` syntax.
56765678
const decl = mod.declPtr(decl_index);
5677-
if (decl.is_pub or src_file == decl.getFileScope()) {
5679+
if (decl.is_pub or (src_file == decl.getFileScope() and checked_namespaces.values()[check_i])) {
56785680
try candidates.append(gpa, decl_index);
56795681
}
56805682
}
@@ -5693,7 +5695,7 @@ fn lookupInNamespace(
56935695
try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);
56945696
const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;
56955697
const sub_ns = ns_ty.getNamespace().?;
5696-
try checked_namespaces.put(gpa, sub_ns, {});
5698+
try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope());
56975699
}
56985700
}
56995701

@@ -6331,6 +6333,7 @@ fn analyzeCall(
63316333
.instructions = .{},
63326334
.label = null,
63336335
.inlining = &inlining,
6336+
.is_typeof = block.is_typeof,
63346337
.is_comptime = is_comptime_call,
63356338
.comptime_reason = comptime_reason,
63366339
.error_return_trace_index = block.error_return_trace_index,
@@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1653016533
// This is only relevant at runtime.
1653116534
if (block.is_comptime or block.is_typeof) return;
1653216535

16533-
// This is only relevant within functions.
16534-
if (sema.func == null) return;
16535-
1653616536
const save_index = inst_data.operand == .none or b: {
1653716537
const operand = try sema.resolveInst(inst_data.operand);
1653816538
const operand_ty = sema.typeOf(operand);
@@ -20179,8 +20179,8 @@ fn analyzeShuffle(
2017920179
.elem_type = elem_ty,
2018020180
});
2018120181

20182-
if (maybe_a_len == null) a = try sema.addConstUndef(a_ty);
20183-
if (maybe_b_len == null) b = try sema.addConstUndef(b_ty);
20182+
if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src);
20183+
if (maybe_b_len == null) b = try sema.addConstUndef(b_ty) else b = try sema.coerce(block, b_ty, b, b_src);
2018420184

2018520185
const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){
2018620186
.{ a_len, a_src, a_ty },
@@ -27503,9 +27503,6 @@ fn analyzeLoad(
2750327503
if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
2750427504
return sema.addConstant(elem_ty, elem_val);
2750527505
}
27506-
if (block.is_typeof) {
27507-
return sema.addConstUndef(elem_ty);
27508-
}
2750927506
}
2751027507

2751127508
return block.addTyOp(.load, elem_ty, ptr);

src/codegen/llvm.zig

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,7 +1966,7 @@ pub const Object = struct {
19661966

19671967
for (tuple.types) |field_ty, i| {
19681968
const field_val = tuple.values[i];
1969-
if (field_val.tag() != .unreachable_value) continue;
1969+
if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
19701970

19711971
const field_size = field_ty.abiSize(target);
19721972
const field_align = field_ty.abiAlignment(target);
@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
29012901

29022902
for (tuple.types) |field_ty, i| {
29032903
const field_val = tuple.values[i];
2904-
if (field_val.tag() != .unreachable_value) continue;
2904+
if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
29052905

29062906
const field_align = field_ty.abiAlignment(target);
29072907
big_align = @max(big_align, field_align);
@@ -3198,7 +3198,8 @@ pub const DeclGen = struct {
31983198
/// There are other similar cases handled here as well.
31993199
fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {
32003200
const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
3201-
.Opaque, .Fn => true,
3201+
.Opaque => true,
3202+
.Fn => !elem_ty.fnInfo().is_generic,
32023203
.Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
32033204
else => elem_ty.hasRuntimeBitsIgnoreComptime(),
32043205
};
@@ -4145,7 +4146,9 @@ pub const DeclGen = struct {
41454146
}
41464147

41474148
const is_fn_body = decl.ty.zigTypeTag() == .Fn;
4148-
if (!is_fn_body and !decl.ty.hasRuntimeBits()) {
4149+
if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or
4150+
(is_fn_body and decl.ty.fnInfo().is_generic))
4151+
{
41494152
return self.lowerPtrToVoid(tv.ty);
41504153
}
41514154

@@ -8671,9 +8674,9 @@ pub const FuncGen = struct {
86718674
const arena = arena_allocator.allocator();
86728675

86738676
const mod = self.dg.module;
8674-
const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{
8675-
try mod.declPtr(enum_decl).getFullyQualifiedName(mod),
8676-
});
8677+
const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8678+
defer self.gpa.free(fqn);
8679+
const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn});
86778680

86788681
var int_tag_type_buffer: Type.Payload.Bits = undefined;
86798682
const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
@@ -8752,9 +8755,9 @@ pub const FuncGen = struct {
87528755
const arena = arena_allocator.allocator();
87538756

87548757
const mod = self.dg.module;
8755-
const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{
8756-
try mod.declPtr(enum_decl).getFullyQualifiedName(mod),
8757-
});
8758+
const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8759+
defer self.gpa.free(fqn);
8760+
const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
87588761

87598762
const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
87608763
const llvm_ret_ty = try self.dg.lowerType(slice_ty);
@@ -10204,7 +10207,7 @@ fn llvmFieldIndex(
1020410207
const tuple = ty.tupleFields();
1020510208
var llvm_field_index: c_uint = 0;
1020610209
for (tuple.types) |field_ty, i| {
10207-
if (tuple.values[i].tag() != .unreachable_value) continue;
10210+
if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
1020810211

1020910212
const field_align = field_ty.abiAlignment(target);
1021010213
big_align = @max(big_align, field_align);
@@ -10216,7 +10219,7 @@ fn llvmFieldIndex(
1021610219
llvm_field_index += 1;
1021710220
}
1021810221

10219-
if (field_index == i) {
10222+
if (field_index <= i) {
1022010223
ptr_pl_buf.* = .{
1022110224
.data = .{
1022210225
.pointee_type = field_ty,
@@ -10249,7 +10252,7 @@ fn llvmFieldIndex(
1024910252
llvm_field_index += 1;
1025010253
}
1025110254

10252-
if (field_index == i) {
10255+
if (field_index <= i) {
1025310256
ptr_pl_buf.* = .{
1025410257
.data = .{
1025510258
.pointee_type = field.ty,
@@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool {
1076810771
const tuple = ty.tupleFields();
1076910772
var count: usize = 0;
1077010773
for (tuple.values) |field_val, i| {
10771-
if (field_val.tag() != .unreachable_value) continue;
10774+
if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;
1077210775

1077310776
count += 1;
1077410777
if (count > max_fields_byval) return true;

src/type.zig

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,9 @@ pub const Type = extern union {
640640
const a_info = a.fnInfo();
641641
const b_info = b.fnInfo();
642642

643-
if (!eql(a_info.return_type, b_info.return_type, mod))
643+
if (a_info.return_type.tag() != .generic_poison and
644+
b_info.return_type.tag() != .generic_poison and
645+
!eql(a_info.return_type, b_info.return_type, mod))
644646
return false;
645647

646648
if (a_info.is_var_args != b_info.is_var_args)
@@ -5757,7 +5759,7 @@ pub const Type = extern union {
57575759

57585760
for (tuple.types) |field_ty, i| {
57595761
const field_val = tuple.values[i];
5760-
if (field_val.tag() != .unreachable_value) {
5762+
if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
57615763
// comptime field
57625764
if (i == index) return offset;
57635765
continue;

test/behavior/eval.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" {
14991499
var index: usize = 0;
15001500
try expect(array[index].? == 'A');
15011501
}
1502+
1503+
test "inline call in @TypeOf inherits is_inline property" {
1504+
const S = struct {
1505+
inline fn doNothing() void {}
1506+
const T = @TypeOf(doNothing());
1507+
};
1508+
try expect(S.T == void);
1509+
}

test/behavior/generics.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" {
405405
};
406406
try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8)));
407407
}
408+
409+
test "generic function passed as comptime argument" {
410+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
411+
412+
const S = struct {
413+
fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
414+
const result = try f(i32, a, b);
415+
try expect(result == 11);
416+
}
417+
};
418+
try S.doMath(std.math.add, 5, 6);
419+
}

test/behavior/pointers.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" {
489489
var p = @ptrCast([*c]const u8, s);
490490
try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0));
491491
}
492+
493+
test "ptrToInt on a generic function" {
494+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
496+
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
497+
if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO
498+
499+
const S = struct {
500+
fn generic(i: anytype) @TypeOf(i) {
501+
return i;
502+
}
503+
fn doTheTest(a: anytype) !void {
504+
try expect(@ptrToInt(a) != 0);
505+
}
506+
};
507+
try S.doTheTest(&S.generic);
508+
}

test/behavior/struct.zig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,3 +1398,23 @@ test "under-aligned struct field" {
13981398
const result = std.mem.readIntNative(u64, array[4..12]);
13991399
try expect(result == 1234);
14001400
}
1401+
1402+
test "address of zero-bit field is equal to address of only field" {
1403+
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1404+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1405+
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1406+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1407+
1408+
{
1409+
const A = struct { b: void = {}, u: u8 };
1410+
var a = A{ .u = 0 };
1411+
const a_ptr = @fieldParentPtr(A, "b", &a.b);
1412+
try std.testing.expectEqual(&a, a_ptr);
1413+
}
1414+
{
1415+
const A = struct { u: u8, b: void = {} };
1416+
var a = A{ .u = 0 };
1417+
const a_ptr = @fieldParentPtr(A, "b", &a.b);
1418+
try std.testing.expectEqual(&a, a_ptr);
1419+
}
1420+
}

test/behavior/tuple.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" {
323323
var s: State = undefined;
324324
try expect(s.do() == 0);
325325
}
326+
327+
test "tuple type with void field and a runtime field" {
328+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
329+
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
330+
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
331+
332+
const T = std.meta.Tuple(&[_]type{ usize, void });
333+
var t: T = .{ 5, {} };
334+
try expect(t[0] == 5);
335+
}

test/behavior/usingnamespace.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ test {
7575
const a = AA.b(42);
7676
try expect(a.x == AA.c().expected);
7777
}
78+
79+
comptime {
80+
_ = @import("usingnamespace/file_1.zig");
81+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub const A = 123;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const std = @import("std");
2+
const expect = std.testing.expect;
3+
const imports = @import("imports.zig");
4+
5+
const A = 456;
6+
7+
test {
8+
try expect(imports.A == 123);
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const file_0 = @import("file_0.zig");
2+
const file_1 = @import("file_1.zig");
3+
4+
pub usingnamespace file_0;
5+
pub usingnamespace file_1;

test/behavior/vector.zig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33
const mem = std.mem;
44
const math = std.math;
55
const expect = std.testing.expect;
6+
const expectEqual = std.testing.expectEqual;
67

78
test "implicit cast vector to array - bool" {
89
if (builtin.zig_backend == .stage1) {
@@ -1231,3 +1232,17 @@ test "modRem with zero divisor" {
12311232
_ = zeros[0];
12321233
}
12331234
}
1235+
1236+
test "array operands to shuffle are coerced to vectors" {
1237+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1238+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1239+
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1240+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1241+
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1242+
1243+
const mask = [5]i32{ -1, 0, 1, 2, 3 };
1244+
1245+
var a = [5]u32{ 3, 5, 7, 9, 0 };
1246+
var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask);
1247+
try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
1248+
}

0 commit comments

Comments
 (0)