| author | |
| committer | |
| log | 60be67d3c0ba6ae15fa7115596734ab1e74fbcd3 |
| tree | 4679e250207c5215d5df51d79a307d41443fd4eb |
| parent | 60a332406c10be922568e11dcc5144bb0f2d7a85 |
4 files changed, 85 insertions(+), 46 deletions(-)
src/Sema.zig+25-20| ... | @@ -2824,9 +2824,6 @@ fn zirTupleDecl( | ... | @@ -2824,9 +2824,6 @@ fn zirTupleDecl( |
| 2824 | } | 2824 | } |
| 2825 | break :init field_init_val.toIntern(); | 2825 | break :init field_init_val.toIntern(); |
| 2826 | } | 2826 | } |
| 2827 | if (try sema.typeHasOnePossibleValue(field_type)) |opv| { | ||
| 2828 | break :init opv.toIntern(); | ||
| 2829 | } | ||
| 2830 | break :init .none; | 2827 | break :init .none; |
| 2831 | }; | 2828 | }; |
| 2832 | } | 2829 | } |
| ... | @@ -21479,18 +21476,8 @@ fn reifyTuple( | ... | @@ -21479,18 +21476,8 @@ fn reifyTuple( |
| 21479 | return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{}); | 21476 | return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{}); |
| 21480 | } | 21477 | } |
| 21481 | 21478 | ||
| 21482 | const default_or_opv: InternPool.Index = default: { | ||
| 21483 | if (field_default_value != .none) { | ||
| 21484 | break :default field_default_value; | ||
| 21485 | } | ||
| 21486 | if (try sema.typeHasOnePossibleValue(field_type)) |opv| { | ||
| 21487 | break :default opv.toIntern(); | ||
| 21488 | } | ||
| 21489 | break :default .none; | ||
| 21490 | }; | ||
| 21491 | |||
| 21492 | field_ty.* = field_type.toIntern(); | 21479 | field_ty.* = field_type.toIntern(); |
| 21493 | field_init.* = default_or_opv; | 21480 | field_init.* = field_default_value; |
| 21494 | } | 21481 | } |
| 21495 | 21482 | ||
| 21496 | return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{ | 21483 | return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{ |
| ... | @@ -36282,13 +36269,31 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -36282,13 +36269,31 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36282 | }, | 36269 | }, |
| 36283 | 36270 | ||
| 36284 | .tuple_type => |tuple| { | 36271 | .tuple_type => |tuple| { |
| 36285 | for (tuple.values.get(ip)) |val| { | 36272 | try ty.resolveLayout(pt); |
| 36286 | if (val == .none) return null; | 36273 | |
| 36274 | if (tuple.types.len == 0) { | ||
| 36275 | return try pt.aggregateValue(ty, &.{}); | ||
| 36287 | } | 36276 | } |
| 36288 | // In this case the struct has all comptime-known fields and | 36277 | |
| 36289 | // therefore has one possible value. | 36278 | const field_vals = try sema.arena.alloc( |
| 36290 | // TODO: write something like getCoercedInts to avoid needing to dupe | 36279 | InternPool.Index, |
| 36291 | return try pt.aggregateValue(ty, try sema.arena.dupe(InternPool.Index, tuple.values.get(ip))); | 36280 | tuple.types.len, |
| 36281 | ); | ||
| 36282 | for ( | ||
| 36283 | field_vals, | ||
| 36284 | tuple.types.get(ip), | ||
| 36285 | tuple.values.get(ip), | ||
| 36286 | ) |*field_val, field_ty, field_comptime_val| { | ||
| 36287 | if (field_comptime_val != .none) { | ||
| 36288 | field_val.* = field_comptime_val; | ||
| 36289 | continue; | ||
| 36290 | } | ||
| 36291 | if (try sema.typeHasOnePossibleValue(.fromInterned(field_ty))) |opv| { | ||
| 36292 | field_val.* = opv.toIntern(); | ||
| 36293 | } else return null; | ||
| 36294 | } | ||
| 36295 | |||
| 36296 | return try pt.aggregateValue(ty, field_vals); | ||
| 36292 | }, | 36297 | }, |
| 36293 | 36298 | ||
| 36294 | .union_type => { | 36299 | .union_type => { |
src/Type.zig+38-25| ... | @@ -2581,15 +2581,30 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { | ... | @@ -2581,15 +2581,30 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2581 | }, | 2581 | }, |
| 2582 | 2582 | ||
| 2583 | .tuple_type => |tuple| { | 2583 | .tuple_type => |tuple| { |
| 2584 | for (tuple.values.get(ip)) |val| { | 2584 | if (tuple.types.len == 0) { |
| 2585 | if (val == .none) return null; | 2585 | return try pt.aggregateValue(ty, &.{}); |
| 2586 | } | 2586 | } |
| 2587 | // In this case the struct has all comptime-known fields and | 2587 | |
| 2588 | // therefore has one possible value. | 2588 | const field_vals = try zcu.gpa.alloc( |
| 2589 | // TODO: write something like getCoercedInts to avoid needing to dupe | 2589 | InternPool.Index, |
| 2590 | const duped_values = try zcu.gpa.dupe(InternPool.Index, tuple.values.get(ip)); | 2590 | tuple.types.len, |
| 2591 | defer zcu.gpa.free(duped_values); | 2591 | ); |
| 2592 | return try pt.aggregateValue(ty, duped_values); | 2592 | defer zcu.gpa.free(field_vals); |
| 2593 | for ( | ||
| 2594 | field_vals, | ||
| 2595 | tuple.types.get(ip), | ||
| 2596 | tuple.values.get(ip), | ||
| 2597 | ) |*field_val, field_ty, field_comptime_val| { | ||
| 2598 | if (field_comptime_val != .none) { | ||
| 2599 | field_val.* = field_comptime_val; | ||
| 2600 | continue; | ||
| 2601 | } | ||
| 2602 | if (try Type.fromInterned(field_ty).onePossibleValue(pt)) |opv| { | ||
| 2603 | field_val.* = opv.toIntern(); | ||
| 2604 | } else return null; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | return try pt.aggregateValue(ty, field_vals); | ||
| 2593 | }, | 2608 | }, |
| 2594 | 2609 | ||
| 2595 | .union_type => { | 2610 | .union_type => { |
| ... | @@ -2630,24 +2645,22 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { | ... | @@ -2630,24 +2645,22 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2630 | .auto, .explicit => { | 2645 | .auto, .explicit => { |
| 2631 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; | 2646 | if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; |
| 2632 | 2647 | ||
| 2633 | switch (enum_type.names.len) { | 2648 | return Value.fromInterned(switch (enum_type.names.len) { |
| 2634 | 0 => { | 2649 | 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }), |
| 2635 | const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); | 2650 | 1 => try pt.intern(.{ .enum_tag = .{ |
| 2636 | return Value.fromInterned(only); | 2651 | .ty = ty.toIntern(), |
| 2637 | }, | 2652 | .int = if (enum_type.values.len == 0) |
| 2638 | 1 => { | 2653 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() |
| 2639 | if (enum_type.values.len == 0) { | 2654 | else |
| 2640 | const only = try pt.intern(.{ .enum_tag = .{ | 2655 | try ip.getCoercedInts( |
| 2641 | .ty = ty.toIntern(), | 2656 | zcu.gpa, |
| 2642 | .int = (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern(), | 2657 | pt.tid, |
| 2643 | } }); | 2658 | ip.indexToKey(enum_type.values.get(ip)[0]).int, |
| 2644 | return Value.fromInterned(only); | 2659 | enum_type.tag_ty, |
| 2645 | } else { | 2660 | ), |
| 2646 | return Value.fromInterned(enum_type.values.get(ip)[0]); | 2661 | } }), |
| 2647 | } | ||
| 2648 | }, | ||
| 2649 | else => return null, | 2662 | else => return null, |
| 2650 | } | 2663 | }); |
| 2651 | }, | 2664 | }, |
| 2652 | } | 2665 | } |
| 2653 | }, | 2666 | }, |
test/behavior/tuple.zig+21| ... | @@ -611,3 +611,24 @@ test "field pointer of underaligned tuple" { | ... | @@ -611,3 +611,24 @@ test "field pointer of underaligned tuple" { |
| 611 | try S.doTheTest(); | 611 | try S.doTheTest(); |
| 612 | try comptime S.doTheTest(); | 612 | try comptime S.doTheTest(); |
| 613 | } | 613 | } |
| 614 | |||
| 615 | test "OPV tuple fields aren't comptime" { | ||
| 616 | const T = struct { void }; | ||
| 617 | const t_info = @typeInfo(T); | ||
| 618 | try expect(!t_info.@"struct".fields[0].is_comptime); | ||
| 619 | |||
| 620 | const T2 = @Type(.{ .@"struct" = .{ | ||
| 621 | .layout = .auto, | ||
| 622 | .fields = &.{.{ | ||
| 623 | .name = "0", | ||
| 624 | .type = void, | ||
| 625 | .default_value_ptr = null, | ||
| 626 | .is_comptime = false, | ||
| 627 | .alignment = @alignOf(void), | ||
| 628 | }}, | ||
| 629 | .decls = &.{}, | ||
| 630 | .is_tuple = true, | ||
| 631 | } }); | ||
| 632 | const t2_info = @typeInfo(T2); | ||
| 633 | try expect(!t2_info.@"struct".fields[0].is_comptime); | ||
| 634 | } |
test/cases/compile_errors/invalid_tuple_to_struct_coercion.zig+1-1| ... | @@ -8,5 +8,5 @@ export fn entry() void { | ... | @@ -8,5 +8,5 @@ export fn entry() void { |
| 8 | 8 | ||
| 9 | // error | 9 | // error |
| 10 | // | 10 | // |
| 11 | // :6:31: error: expected type 'tmp.S', found 'struct { comptime void = {} }' | 11 | // :6:31: error: expected type 'tmp.S', found 'struct { void }' |
| 12 | // :1:11: note: struct declared here | 12 | // :1:11: note: struct declared here |