authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-31 17:24:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-31 17:25:42-07:00
log982acc22fd8674a9efbe1e65e037c464ba610882
tree46593d2090d8d3c3524499cc9eddb06be9401c32
parent79a93914142e33636c37957fd513d42f4ac46060

stage2: compile error for invalid `var` type


6 files changed, 117 insertions(+), 50 deletions(-)

BRANCH_TODO deleted-2
......@@ -1,2 +0,0 @@
1 * compile error for "variable of type '{}' must be const or comptime" after resolving types
2 * test with branches
src/Module.zig+6
......@@ -3421,3 +3421,9 @@ pub fn getTarget(self: Module) Target {
34213421pub fn optimizeMode(self: Module) std.builtin.Mode {
34223422 return self.comp.bin_file.options.optimize_mode;
34233423}
3424
3425pub fn validateVarType(mod: *Module, scope: *Scope, src: usize, ty: Type) !void {
3426 if (!ty.isValidVarType(false)) {
3427 return mod.fail(scope, src, "variable of type '{}' must be const or comptime", .{ty});
3428 }
3429}
src/astgen.zig+1-1
......@@ -625,7 +625,7 @@ fn varDecl(
625625 const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst);
626626 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
627627 } else a: {
628 const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred);
628 const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred_mut);
629629 resolve_inferred_alloc = &alloc.base;
630630 break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } };
631631 };
src/type.zig+68-34
......@@ -78,7 +78,8 @@ pub const Type = extern union {
7878 .const_slice,
7979 .mut_slice,
8080 .pointer,
81 .inferred_alloc,
81 .inferred_alloc_const,
82 .inferred_alloc_mut,
8283 => return .Pointer,
8384
8485 .optional,
......@@ -159,7 +160,8 @@ pub const Type = extern union {
159160 .optional_single_mut_pointer,
160161 => self.cast(Payload.ElemType),
161162
162 .inferred_alloc => unreachable,
163 .inferred_alloc_const => unreachable,
164 .inferred_alloc_mut => unreachable,
163165
164166 else => null,
165167 };
......@@ -387,7 +389,8 @@ pub const Type = extern union {
387389 .enum_literal,
388390 .anyerror_void_error_union,
389391 .@"anyframe",
390 .inferred_alloc,
392 .inferred_alloc_const,
393 .inferred_alloc_mut,
391394 => unreachable,
392395
393396 .array_u8,
......@@ -690,7 +693,8 @@ pub const Type = extern union {
690693 const name = ty.castTag(.error_set_single).?.data;
691694 return out_stream.print("error{{{s}}}", .{name});
692695 },
693 .inferred_alloc => return out_stream.writeAll("(inferred allocation type)"),
696 .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"),
697 .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"),
694698 }
695699 unreachable;
696700 }
......@@ -738,7 +742,8 @@ pub const Type = extern union {
738742 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
739743 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
740744 .enum_literal => return Value.initTag(.enum_literal_type),
741 .inferred_alloc => unreachable,
745 .inferred_alloc_const => unreachable,
746 .inferred_alloc_mut => unreachable,
742747 else => return Value.Tag.ty.create(allocator, self),
743748 }
744749 }
......@@ -810,7 +815,8 @@ pub const Type = extern union {
810815 .empty_struct,
811816 => false,
812817
813 .inferred_alloc => unreachable,
818 .inferred_alloc_const => unreachable,
819 .inferred_alloc_mut => unreachable,
814820 };
815821 }
816822
......@@ -928,7 +934,8 @@ pub const Type = extern union {
928934 .@"undefined",
929935 .enum_literal,
930936 .empty_struct,
931 .inferred_alloc,
937 .inferred_alloc_const,
938 .inferred_alloc_mut,
932939 => unreachable,
933940 };
934941 }
......@@ -952,7 +959,8 @@ pub const Type = extern union {
952959 .enum_literal => unreachable,
953960 .single_const_pointer_to_comptime_int => unreachable,
954961 .empty_struct => unreachable,
955 .inferred_alloc => unreachable,
962 .inferred_alloc_const => unreachable,
963 .inferred_alloc_mut => unreachable,
956964
957965 .u8,
958966 .i8,
......@@ -1131,7 +1139,8 @@ pub const Type = extern union {
11311139 .single_const_pointer,
11321140 .single_mut_pointer,
11331141 .single_const_pointer_to_comptime_int,
1134 .inferred_alloc,
1142 .inferred_alloc_const,
1143 .inferred_alloc_mut,
11351144 => true,
11361145
11371146 .pointer => self.castTag(.pointer).?.data.size == .One,
......@@ -1214,7 +1223,8 @@ pub const Type = extern union {
12141223 .single_const_pointer,
12151224 .single_mut_pointer,
12161225 .single_const_pointer_to_comptime_int,
1217 .inferred_alloc,
1226 .inferred_alloc_const,
1227 .inferred_alloc_mut,
12181228 => .One,
12191229
12201230 .pointer => self.castTag(.pointer).?.data.size,
......@@ -1285,7 +1295,8 @@ pub const Type = extern union {
12851295 .error_set,
12861296 .error_set_single,
12871297 .empty_struct,
1288 .inferred_alloc,
1298 .inferred_alloc_const,
1299 .inferred_alloc_mut,
12891300 => false,
12901301
12911302 .const_slice,
......@@ -1358,7 +1369,8 @@ pub const Type = extern union {
13581369 .error_set,
13591370 .error_set_single,
13601371 .empty_struct,
1361 .inferred_alloc,
1372 .inferred_alloc_const,
1373 .inferred_alloc_mut,
13621374 => false,
13631375
13641376 .single_const_pointer,
......@@ -1440,7 +1452,8 @@ pub const Type = extern union {
14401452 .error_set,
14411453 .error_set_single,
14421454 .empty_struct,
1443 .inferred_alloc,
1455 .inferred_alloc_const,
1456 .inferred_alloc_mut,
14441457 => false,
14451458
14461459 .pointer => {
......@@ -1517,7 +1530,8 @@ pub const Type = extern union {
15171530 .error_set,
15181531 .error_set_single,
15191532 .empty_struct,
1520 .inferred_alloc,
1533 .inferred_alloc_const,
1534 .inferred_alloc_mut,
15211535 => false,
15221536
15231537 .pointer => {
......@@ -1636,7 +1650,8 @@ pub const Type = extern union {
16361650 .error_set => unreachable,
16371651 .error_set_single => unreachable,
16381652 .empty_struct => unreachable,
1639 .inferred_alloc => unreachable,
1653 .inferred_alloc_const => unreachable,
1654 .inferred_alloc_mut => unreachable,
16401655
16411656 .array => self.castTag(.array).?.data.elem_type,
16421657 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
......@@ -1758,7 +1773,8 @@ pub const Type = extern union {
17581773 .error_set,
17591774 .error_set_single,
17601775 .empty_struct,
1761 .inferred_alloc,
1776 .inferred_alloc_const,
1777 .inferred_alloc_mut,
17621778 => unreachable,
17631779
17641780 .array => self.castTag(.array).?.data.len,
......@@ -1825,7 +1841,8 @@ pub const Type = extern union {
18251841 .error_set,
18261842 .error_set_single,
18271843 .empty_struct,
1828 .inferred_alloc,
1844 .inferred_alloc_const,
1845 .inferred_alloc_mut,
18291846 => unreachable,
18301847
18311848 .single_const_pointer,
......@@ -1909,7 +1926,8 @@ pub const Type = extern union {
19091926 .error_set,
19101927 .error_set_single,
19111928 .empty_struct,
1912 .inferred_alloc,
1929 .inferred_alloc_const,
1930 .inferred_alloc_mut,
19131931 => false,
19141932
19151933 .int_signed,
......@@ -1985,7 +2003,8 @@ pub const Type = extern union {
19852003 .error_set,
19862004 .error_set_single,
19872005 .empty_struct,
1988 .inferred_alloc,
2006 .inferred_alloc_const,
2007 .inferred_alloc_mut,
19892008 => false,
19902009
19912010 .int_unsigned,
......@@ -2051,7 +2070,8 @@ pub const Type = extern union {
20512070 .error_set,
20522071 .error_set_single,
20532072 .empty_struct,
2054 .inferred_alloc,
2073 .inferred_alloc_const,
2074 .inferred_alloc_mut,
20552075 => unreachable,
20562076
20572077 .int_unsigned => .{
......@@ -2141,7 +2161,8 @@ pub const Type = extern union {
21412161 .error_set,
21422162 .error_set_single,
21432163 .empty_struct,
2144 .inferred_alloc,
2164 .inferred_alloc_const,
2165 .inferred_alloc_mut,
21452166 => false,
21462167
21472168 .usize,
......@@ -2254,7 +2275,8 @@ pub const Type = extern union {
22542275 .error_set,
22552276 .error_set_single,
22562277 .empty_struct,
2257 .inferred_alloc,
2278 .inferred_alloc_const,
2279 .inferred_alloc_mut,
22582280 => unreachable,
22592281 };
22602282 }
......@@ -2333,7 +2355,8 @@ pub const Type = extern union {
23332355 .error_set,
23342356 .error_set_single,
23352357 .empty_struct,
2336 .inferred_alloc,
2358 .inferred_alloc_const,
2359 .inferred_alloc_mut,
23372360 => unreachable,
23382361 }
23392362 }
......@@ -2411,7 +2434,8 @@ pub const Type = extern union {
24112434 .error_set,
24122435 .error_set_single,
24132436 .empty_struct,
2414 .inferred_alloc,
2437 .inferred_alloc_const,
2438 .inferred_alloc_mut,
24152439 => unreachable,
24162440 }
24172441 }
......@@ -2489,7 +2513,8 @@ pub const Type = extern union {
24892513 .error_set,
24902514 .error_set_single,
24912515 .empty_struct,
2492 .inferred_alloc,
2516 .inferred_alloc_const,
2517 .inferred_alloc_mut,
24932518 => unreachable,
24942519 };
24952520 }
......@@ -2564,7 +2589,8 @@ pub const Type = extern union {
25642589 .error_set,
25652590 .error_set_single,
25662591 .empty_struct,
2567 .inferred_alloc,
2592 .inferred_alloc_const,
2593 .inferred_alloc_mut,
25682594 => unreachable,
25692595 };
25702596 }
......@@ -2639,7 +2665,8 @@ pub const Type = extern union {
26392665 .error_set,
26402666 .error_set_single,
26412667 .empty_struct,
2642 .inferred_alloc,
2668 .inferred_alloc_const,
2669 .inferred_alloc_mut,
26432670 => unreachable,
26442671 };
26452672 }
......@@ -2714,7 +2741,8 @@ pub const Type = extern union {
27142741 .error_set,
27152742 .error_set_single,
27162743 .empty_struct,
2717 .inferred_alloc,
2744 .inferred_alloc_const,
2745 .inferred_alloc_mut,
27182746 => false,
27192747 };
27202748 }
......@@ -2807,7 +2835,8 @@ pub const Type = extern union {
28072835 ty = ty.castTag(.pointer).?.data.pointee_type;
28082836 continue;
28092837 },
2810 .inferred_alloc => unreachable,
2838 .inferred_alloc_const => unreachable,
2839 .inferred_alloc_mut => unreachable,
28112840 };
28122841 }
28132842
......@@ -2876,7 +2905,8 @@ pub const Type = extern union {
28762905 .error_set,
28772906 .error_set_single,
28782907 .empty_struct,
2879 .inferred_alloc,
2908 .inferred_alloc_const,
2909 .inferred_alloc_mut,
28802910 => return false,
28812911
28822912 .c_const_pointer,
......@@ -2962,7 +2992,8 @@ pub const Type = extern union {
29622992 .c_const_pointer,
29632993 .c_mut_pointer,
29642994 .pointer,
2965 .inferred_alloc,
2995 .inferred_alloc_const,
2996 .inferred_alloc_mut,
29662997 => unreachable,
29672998
29682999 .empty_struct => self.castTag(.empty_struct).?.data,
......@@ -3077,7 +3108,9 @@ pub const Type = extern union {
30773108 /// This is a special value that tracks a set of types that have been stored
30783109 /// to an inferred allocation. It does not support most of the normal type queries.
30793110 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
3080 inferred_alloc, // See last_no_payload_tag below.
3111 inferred_alloc_mut,
3112 /// Same as `inferred_alloc_mut` but the local is `var` not `const`.
3113 inferred_alloc_const, // See last_no_payload_tag below.
30813114 // After this, the tag requires a payload.
30823115
30833116 array_u8,
......@@ -3105,7 +3138,7 @@ pub const Type = extern union {
31053138 error_set_single,
31063139 empty_struct,
31073140
3108 pub const last_no_payload_tag = Tag.inferred_alloc;
3141 pub const last_no_payload_tag = Tag.inferred_alloc_const;
31093142 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
31103143
31113144 pub fn Type(comptime t: Tag) type {
......@@ -3152,7 +3185,8 @@ pub const Type = extern union {
31523185 .anyerror_void_error_union,
31533186 .@"anyframe",
31543187 .const_slice_u8,
3155 .inferred_alloc,
3188 .inferred_alloc_const,
3189 .inferred_alloc_mut,
31563190 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
31573191
31583192 .array_u8,
src/zir_sema.zig+33-13
......@@ -30,8 +30,18 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
3030 switch (old_inst.tag) {
3131 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),
3232 .alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?),
33 .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),
34 .alloc_inferred_mut => return analyzeInstAllocInferredMut(mod, scope, old_inst.castTag(.alloc_inferred_mut).?),
33 .alloc_inferred => return analyzeInstAllocInferred(
34 mod,
35 scope,
36 old_inst.castTag(.alloc_inferred).?,
37 .inferred_alloc_const,
38 ),
39 .alloc_inferred_mut => return analyzeInstAllocInferred(
40 mod,
41 scope,
42 old_inst.castTag(.alloc_inferred_mut).?,
43 .inferred_alloc_mut,
44 ),
3545 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
3646 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
3747 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
......@@ -423,15 +433,18 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro
423433
424434fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
425435 const var_type = try resolveType(mod, scope, inst.positionals.operand);
426 if (!var_type.isValidVarType(false)) {
427 return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type});
428 }
436 try mod.validateVarType(scope, inst.base.src, var_type);
429437 const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One);
430438 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
431439 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
432440}
433441
434fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
442fn analyzeInstAllocInferred(
443 mod: *Module,
444 scope: *Scope,
445 inst: *zir.Inst.NoOp,
446 mut_tag: Type.Tag,
447) InnerError!*Inst {
435448 const val_payload = try scope.arena().create(Value.Payload.InferredAlloc);
436449 val_payload.* = .{
437450 .data = .{},
......@@ -441,7 +454,11 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I
441454 // to a normal instruction when we hit `resolve_inferred_alloc`. So we append
442455 // to the block even though it is currently a `.constant`.
443456 const result = try mod.constInst(scope, inst.base.src, .{
444 .ty = Type.initTag(.inferred_alloc),
457 .ty = switch (mut_tag) {
458 .inferred_alloc_const => Type.initTag(.inferred_alloc_const),
459 .inferred_alloc_mut => Type.initTag(.inferred_alloc_mut),
460 else => unreachable,
461 },
445462 .val = Value.initPayload(&val_payload.base),
446463 });
447464 const block = try mod.requireFunctionBlock(scope, inst.base.src);
......@@ -449,10 +466,6 @@ fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) I
449466 return result;
450467}
451468
452fn analyzeInstAllocInferredMut(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
453 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstAllocInferredMut", .{});
454}
455
456469fn analyzeInstResolveInferredAlloc(
457470 mod: *Module,
458471 scope: *Scope,
......@@ -463,8 +476,15 @@ fn analyzeInstResolveInferredAlloc(
463476 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
464477 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
465478 const final_elem_ty = try mod.resolvePeerTypes(scope, peer_inst_list);
466 const is_mut = true;
467 const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, is_mut, .One);
479 const var_is_mut = switch (ptr.ty.tag()) {
480 .inferred_alloc_const => false,
481 .inferred_alloc_mut => true,
482 else => unreachable,
483 };
484 if (var_is_mut) {
485 try mod.validateVarType(scope, inst.base.src, final_elem_ty);
486 }
487 const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, true, .One);
468488
469489 // Change it to a normal alloc.
470490 ptr.ty = final_ptr_ty;
test/stage2/test.zig+9
......@@ -1322,4 +1322,13 @@ pub fn addCases(ctx: *TestContext) !void {
13221322 \\}
13231323 , &[_][]const u8{":2:5: error: unused for label"});
13241324 }
1325
1326 {
1327 var case = ctx.exe("bad inferred variable type", linux_x64);
1328 case.addError(
1329 \\export fn foo() void {
1330 \\ var x = null;
1331 \\}
1332 , &[_][]const u8{":2:9: error: variable of type '@Type(.Null)' must be const or comptime"});
1333 }
13251334}