@@ -7717,6 +7717,7 @@ fn typeOf(
|
||||
|
||||
var typeof_scope = gz.makeSubBlock(scope);
|
||||
typeof_scope.force_comptime = false;
|
||||
typeof_scope.c_import = false;
|
||||
defer typeof_scope.unstack();
|
||||
|
||||
const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node);
|
||||
@@ -8575,6 +8576,8 @@ fn cImport(
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
if (gz.c_import) return gz.astgen.failNode(node, "cannot nest @cImport", .{});
|
||||
|
||||
var block_scope = gz.makeSubBlock(scope);
|
||||
block_scope.force_comptime = true;
|
||||
block_scope.c_import = true;
|
||||
|
||||
248
src/Sema.zig
248
src/Sema.zig
@@ -5105,6 +5105,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
.is_typeof = parent_block.is_typeof,
|
||||
.want_safety = parent_block.want_safety,
|
||||
.float_mode = parent_block.float_mode,
|
||||
.c_import_buf = parent_block.c_import_buf,
|
||||
.runtime_cond = parent_block.runtime_cond,
|
||||
.runtime_loop = parent_block.runtime_loop,
|
||||
.runtime_index = parent_block.runtime_index,
|
||||
@@ -7031,16 +7032,21 @@ fn instantiateGenericCall(
|
||||
}
|
||||
const arg = uncasted_args[arg_i];
|
||||
if (is_comptime) {
|
||||
if (try sema.resolveMaybeUndefVal(arg)) |arg_val| {
|
||||
const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
|
||||
child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
|
||||
} else {
|
||||
return sema.failWithNeededComptime(block, .unneeded, "");
|
||||
}
|
||||
const arg_val = (try sema.resolveMaybeUndefVal(arg)).?;
|
||||
const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val);
|
||||
child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
|
||||
} else if (is_anytype) {
|
||||
const arg_ty = sema.typeOf(arg);
|
||||
if (try sema.typeRequiresComptime(arg_ty)) {
|
||||
const arg_val = try sema.resolveConstValue(block, .unneeded, arg, "");
|
||||
const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
|
||||
error.NeededSourceLocation => {
|
||||
const decl = sema.mod.declPtr(block.src_decl);
|
||||
const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);
|
||||
_ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
const child_arg = try child_sema.addConstant(arg_ty, arg_val);
|
||||
child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
|
||||
} else {
|
||||
@@ -7575,7 +7581,8 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag()) {
|
||||
.Enum => operand,
|
||||
.Union => blk: {
|
||||
const tag_ty = operand_ty.unionTagType() orelse {
|
||||
const union_ty = try sema.resolveTypeFields(operand_ty);
|
||||
const tag_ty = union_ty.unionTagType() orelse {
|
||||
return sema.fail(
|
||||
block,
|
||||
operand_src,
|
||||
@@ -9691,10 +9698,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
};
|
||||
|
||||
const maybe_union_ty = blk: {
|
||||
const zir_tags = sema.code.instructions.items(.tag);
|
||||
const zir_data = sema.code.instructions.items(.data);
|
||||
const cond_index = Zir.refToIndex(extra.data.operand).?;
|
||||
const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
|
||||
break :blk sema.typeOf(raw_operand);
|
||||
const target_ty = sema.typeOf(raw_operand);
|
||||
break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.elemType() else target_ty;
|
||||
};
|
||||
const union_originally = maybe_union_ty.zigTypeTag() == .Union;
|
||||
|
||||
@@ -10260,6 +10269,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
.comptime_reason = block.comptime_reason,
|
||||
.is_typeof = block.is_typeof,
|
||||
.switch_else_err_ty = else_error_ty,
|
||||
.c_import_buf = block.c_import_buf,
|
||||
.runtime_cond = block.runtime_cond,
|
||||
.runtime_loop = block.runtime_loop,
|
||||
.runtime_index = block.runtime_index,
|
||||
@@ -13479,7 +13489,6 @@ fn zirOverflowArithmetic(
|
||||
const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
|
||||
|
||||
const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
|
||||
const ov_ty = tuple_ty.tupleFields().types[1];
|
||||
// TODO: Remove and use `ov_ty` instead.
|
||||
// This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`.
|
||||
const overflowed_ty = if (dest_ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, dest_ty.vectorLen(), Type.bool) else Type.bool;
|
||||
@@ -13630,14 +13639,7 @@ fn zirOverflowArithmetic(
|
||||
try sema.storePtr2(block, src, ptr, ptr_src, wrapped, src, .store);
|
||||
|
||||
const overflow_bit = try sema.tupleFieldValByIndex(block, src, tuple, 1, tuple_ty);
|
||||
const zero_ov_val = if (dest_ty.zigTypeTag() == .Vector) try Value.Tag.repeated.create(sema.arena, Value.zero) else Value.zero;
|
||||
const zero_ov = try sema.addConstant(ov_ty, zero_ov_val);
|
||||
|
||||
const overflowed_inst = if (dest_ty.zigTypeTag() == .Vector)
|
||||
block.addCmpVector(overflow_bit, .zero, .neq, try sema.addType(ov_ty))
|
||||
else
|
||||
block.addBinOp(.cmp_neq, overflow_bit, zero_ov);
|
||||
return overflowed_inst;
|
||||
return block.addBitCast(overflowed_ty, overflow_bit);
|
||||
};
|
||||
|
||||
try sema.storePtr2(block, src, ptr, ptr_src, result.wrapped, src, .store);
|
||||
@@ -22675,7 +22677,8 @@ fn fieldPtr(
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
if (child_type.unionTagType()) |enum_ty| {
|
||||
const union_ty = try sema.resolveTypeFields(child_type);
|
||||
if (union_ty.unionTagType()) |enum_ty| {
|
||||
if (enum_ty.enumFieldIndex(field_name)) |field_index| {
|
||||
const field_index_u32 = @intCast(u32, field_index);
|
||||
var anon_decl = try block.startAnonDecl();
|
||||
@@ -29101,20 +29104,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
}
|
||||
|
||||
struct_obj.status = .have_layout;
|
||||
|
||||
// In case of querying the ABI alignment of this struct, we will ask
|
||||
// for hasRuntimeBits() of each field, so we need "requires comptime"
|
||||
// to be known already before this function returns.
|
||||
for (struct_obj.fields.values()) |field, i| {
|
||||
_ = sema.typeRequiresComptime(field.ty) catch |err| switch (err) {
|
||||
error.AnalysisFail => {
|
||||
const msg = sema.err orelse return err;
|
||||
try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
|
||||
return err;
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
}
|
||||
// otherwise it's a tuple; no need to resolve anything
|
||||
}
|
||||
@@ -29278,6 +29268,198 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
};
|
||||
}
|
||||
union_obj.status = .have_layout;
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
}
|
||||
|
||||
// In case of querying the ABI alignment of this struct, we will ask
|
||||
// for hasRuntimeBits() of each field, so we need "requires comptime"
|
||||
// to be known already before this function returns.
|
||||
pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
return switch (ty.tag()) {
|
||||
.u1,
|
||||
.u8,
|
||||
.i8,
|
||||
.u16,
|
||||
.i16,
|
||||
.u29,
|
||||
.u32,
|
||||
.i32,
|
||||
.u64,
|
||||
.i64,
|
||||
.u128,
|
||||
.i128,
|
||||
.usize,
|
||||
.isize,
|
||||
.c_short,
|
||||
.c_ushort,
|
||||
.c_int,
|
||||
.c_uint,
|
||||
.c_long,
|
||||
.c_ulong,
|
||||
.c_longlong,
|
||||
.c_ulonglong,
|
||||
.c_longdouble,
|
||||
.f16,
|
||||
.f32,
|
||||
.f64,
|
||||
.f80,
|
||||
.f128,
|
||||
.anyopaque,
|
||||
.bool,
|
||||
.void,
|
||||
.anyerror,
|
||||
.noreturn,
|
||||
.@"anyframe",
|
||||
.null,
|
||||
.undefined,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.call_options,
|
||||
.prefetch_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.manyptr_const_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
.const_slice_u8_sentinel_0,
|
||||
.anyerror_void_error_union,
|
||||
.empty_struct_literal,
|
||||
.empty_struct,
|
||||
.error_set,
|
||||
.error_set_single,
|
||||
.error_set_inferred,
|
||||
.error_set_merged,
|
||||
.@"opaque",
|
||||
.generic_poison,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.int_signed,
|
||||
.int_unsigned,
|
||||
.enum_simple,
|
||||
=> false,
|
||||
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.type,
|
||||
.comptime_int,
|
||||
.comptime_float,
|
||||
.enum_literal,
|
||||
.type_info,
|
||||
// These are function bodies, not function pointers.
|
||||
.fn_noreturn_no_args,
|
||||
.fn_void_no_args,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.function,
|
||||
=> true,
|
||||
|
||||
.var_args_param => unreachable,
|
||||
.inferred_alloc_mut => unreachable,
|
||||
.inferred_alloc_const => unreachable,
|
||||
.bound_fn => unreachable,
|
||||
|
||||
.array,
|
||||
.array_sentinel,
|
||||
.vector,
|
||||
=> return sema.resolveTypeRequiresComptime(ty.childType()),
|
||||
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
.many_mut_pointer,
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
.const_slice,
|
||||
.mut_slice,
|
||||
=> {
|
||||
const child_ty = ty.childType();
|
||||
if (child_ty.zigTypeTag() == .Fn) {
|
||||
return child_ty.fnInfo().is_generic;
|
||||
} else {
|
||||
return sema.resolveTypeRequiresComptime(child_ty);
|
||||
}
|
||||
},
|
||||
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> {
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
return sema.resolveTypeRequiresComptime(ty.optionalChild(&buf));
|
||||
},
|
||||
|
||||
.tuple, .anon_struct => {
|
||||
const tuple = ty.tupleFields();
|
||||
for (tuple.types) |field_ty, i| {
|
||||
const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
|
||||
if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
.@"struct" => {
|
||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||
switch (struct_obj.requires_comptime) {
|
||||
.no, .wip => return false,
|
||||
.yes => return true,
|
||||
.unknown => {
|
||||
var requires_comptime = false;
|
||||
struct_obj.requires_comptime = .wip;
|
||||
for (struct_obj.fields.values()) |field| {
|
||||
if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
|
||||
}
|
||||
if (requires_comptime) {
|
||||
struct_obj.requires_comptime = .yes;
|
||||
} else {
|
||||
struct_obj.requires_comptime = .no;
|
||||
}
|
||||
return requires_comptime;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
.@"union", .union_safety_tagged, .union_tagged => {
|
||||
const union_obj = ty.cast(Type.Payload.Union).?.data;
|
||||
switch (union_obj.requires_comptime) {
|
||||
.no, .wip => return false,
|
||||
.yes => return true,
|
||||
.unknown => {
|
||||
var requires_comptime = false;
|
||||
union_obj.requires_comptime = .wip;
|
||||
for (union_obj.fields.values()) |field| {
|
||||
if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
|
||||
}
|
||||
if (requires_comptime) {
|
||||
union_obj.requires_comptime = .yes;
|
||||
} else {
|
||||
union_obj.requires_comptime = .no;
|
||||
}
|
||||
return requires_comptime;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
.error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
|
||||
.anyframe_T => {
|
||||
const child_ty = ty.castTag(.anyframe_T).?.data;
|
||||
return sema.resolveTypeRequiresComptime(child_ty);
|
||||
},
|
||||
.enum_numbered => {
|
||||
const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
|
||||
return sema.resolveTypeRequiresComptime(tag_ty);
|
||||
},
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
|
||||
return sema.resolveTypeRequiresComptime(tag_ty);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
|
||||
|
||||
@@ -1287,7 +1287,14 @@ test "noreturn field in union" {
|
||||
try expect(a == .a);
|
||||
},
|
||||
}
|
||||
try expect(count == 5);
|
||||
switch (a) {
|
||||
.a => count += 1,
|
||||
.b, .c => |*val| {
|
||||
_ = val;
|
||||
@compileError("bad");
|
||||
},
|
||||
}
|
||||
try expect(count == 6);
|
||||
}
|
||||
|
||||
test "union and enum field order doesn't match" {
|
||||
|
||||
@@ -977,27 +977,35 @@ test "@addWithOverflow" {
|
||||
fn doTheTest() !void {
|
||||
{
|
||||
var result: @Vector(4, u8) = undefined;
|
||||
var overflow = @addWithOverflow(@Vector(4, u8), @Vector(4, u8){ 250, 250, 250, 250 }, @Vector(4, u8){ 0, 5, 6, 10 }, &result);
|
||||
var lhs = @Vector(4, u8){ 250, 250, 250, 250 };
|
||||
var rhs = @Vector(4, u8){ 0, 5, 6, 10 };
|
||||
var overflow = @addWithOverflow(@Vector(4, u8), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, false, true, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
{
|
||||
var result: @Vector(4, i8) = undefined;
|
||||
var overflow = @addWithOverflow(@Vector(4, i8), @Vector(4, i8){ -125, -125, 125, 125 }, @Vector(4, i8){ -3, -4, 2, 3 }, &result);
|
||||
var lhs = @Vector(4, i8){ -125, -125, 125, 125 };
|
||||
var rhs = @Vector(4, i8){ -3, -4, 2, 3 };
|
||||
var overflow = @addWithOverflow(@Vector(4, i8), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
{
|
||||
var result: @Vector(4, u1) = undefined;
|
||||
var overflow = @addWithOverflow(@Vector(4, u1), @Vector(4, u1){ 0, 0, 1, 1 }, @Vector(4, u1){ 0, 1, 0, 1 }, &result);
|
||||
var lhs = @Vector(4, u1){ 0, 0, 1, 1 };
|
||||
var rhs = @Vector(4, u1){ 0, 1, 0, 1 };
|
||||
var overflow = @addWithOverflow(@Vector(4, u1), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, false, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
{
|
||||
var result: @Vector(4, u0) = undefined;
|
||||
var overflow = @addWithOverflow(@Vector(4, u0), @Vector(4, u0){ 0, 0, 0, 0 }, @Vector(4, u0){ 0, 0, 0, 0 }, &result);
|
||||
var lhs = @Vector(4, u0){ 0, 0, 0, 0 };
|
||||
var rhs = @Vector(4, u0){ 0, 0, 0, 0 };
|
||||
var overflow = @addWithOverflow(@Vector(4, u0), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, false, false, false };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1019,15 +1027,19 @@ test "@subWithOverflow" {
|
||||
fn doTheTest() !void {
|
||||
{
|
||||
var result: @Vector(2, u8) = undefined;
|
||||
var overflow = @subWithOverflow(@Vector(2, u8), @Vector(2, u8){ 5, 5 }, @Vector(2, u8){ 5, 6 }, &result);
|
||||
var lhs = @Vector(2, u8){ 5, 5 };
|
||||
var rhs = @Vector(2, u8){ 5, 6 };
|
||||
var overflow = @subWithOverflow(@Vector(2, u8), lhs, rhs, &result);
|
||||
var expected: @Vector(2, bool) = .{ false, true };
|
||||
try expect(mem.eql(bool, &@as([2]bool, overflow), &@as([2]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
{
|
||||
var result: @Vector(4, i8) = undefined;
|
||||
var overflow = @subWithOverflow(@Vector(4, i8), @Vector(4, i8){ -120, -120, 120, 120 }, @Vector(4, i8){ 8, 9, -7, -8 }, &result);
|
||||
var lhs = @Vector(4, i8){ -120, -120, 120, 120 };
|
||||
var rhs = @Vector(4, i8){ 8, 9, -7, -8 };
|
||||
var overflow = @subWithOverflow(@Vector(4, i8), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1048,9 +1060,11 @@ test "@mulWithOverflow" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var result: @Vector(4, u8) = undefined;
|
||||
var overflow = @mulWithOverflow(@Vector(4, u8), @Vector(4, u8){ 10, 10, 10, 10 }, @Vector(4, u8){ 25, 26, 0, 30 }, &result);
|
||||
var lhs = @Vector(4, u8){ 10, 10, 10, 10 };
|
||||
var rhs = @Vector(4, u8){ 25, 26, 0, 30 };
|
||||
var overflow = @mulWithOverflow(@Vector(4, u8), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, true, false, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
@@ -1062,6 +1076,7 @@ test "@shlWithOverflow" {
|
||||
// stage1 doesn't support vector args
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
@@ -1070,9 +1085,11 @@ test "@shlWithOverflow" {
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var result: @Vector(4, u8) = undefined;
|
||||
var overflow = @shlWithOverflow(@Vector(4, u8), @Vector(4, u8){ 0, 1, 8, 255 }, @Vector(4, u3){ 7, 7, 7, 7 }, &result);
|
||||
var lhs = @Vector(4, u8){ 0, 1, 8, 255 };
|
||||
var rhs = @Vector(4, u3){ 7, 7, 7, 7 };
|
||||
var overflow = @shlWithOverflow(@Vector(4, u8), lhs, rhs, &result);
|
||||
var expected: @Vector(4, bool) = .{ false, false, true, true };
|
||||
try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
|
||||
try expectEqual(expected, overflow);
|
||||
}
|
||||
};
|
||||
try S.doTheTest();
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
const S = struct {
|
||||
fn foo(b: u32, c: anytype) void {
|
||||
const C = struct {
|
||||
c: @TypeOf(c),
|
||||
b: u32,
|
||||
};
|
||||
bar(C{ .c = c, .b = b });
|
||||
}
|
||||
fn bar(_: anytype) void {}
|
||||
};
|
||||
pub export fn entry() void {
|
||||
S.foo(0, u32);
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:14: error: unable to resolve comptime value
|
||||
// :7:14: note: argument to parameter with comptime-only type must be comptime-known
|
||||
15
test/cases/compile_errors/cimport.zig
Normal file
15
test/cases/compile_errors/cimport.zig
Normal file
@@ -0,0 +1,15 @@
|
||||
const b = @cDefine("foo", "1");
|
||||
const c = @cImport({
|
||||
_ = @TypeOf(@cDefine("foo", "1"));
|
||||
});
|
||||
const d = @cImport({
|
||||
_ = @cImport(@cDefine("foo", "1"));
|
||||
});
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:11: error: C define valid only inside C import block
|
||||
// :3:17: error: C define valid only inside C import block
|
||||
// :6:9: error: cannot nest @cImport
|
||||
@@ -0,0 +1,16 @@
|
||||
const T = union(enum) {
|
||||
a,
|
||||
pub fn f(self: T) void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
pub export fn entry() void {
|
||||
T.a.f();
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :8:8: error: no field or member function named 'f' in '@typeInfo(tmp.T).Union.tag_type.?'
|
||||
// :1:11: note: enum declared here
|
||||
Reference in New Issue
Block a user