authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-09 22:46:08-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-09 22:46:08-04:00
logbc0a60c7a6e772a40fc19becd46f89f34f502759
treeea48f9759ed2cb10146c441ef45db289729befe8
parent5fdf3fa1954f8f8f2a4558723078c0b1400b8574

more compile errors for non-const variables of things

closes #456

3 files changed, 108 insertions(+), 66 deletions(-)

src/analyze.cpp+1
......@@ -2510,6 +2510,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
25102510
25112511 IrInstruction *init_value = nullptr;
25122512
2513 // TODO more validation for types that can't be used for export/extern variables
25132514 TypeTableEntry *implicit_type = nullptr;
25142515 if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
25152516 implicit_type = explicit_type;
src/ir.cpp+71-52
......@@ -9794,6 +9794,58 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi
97949794 zig_unreachable();
97959795}
97969796
9797enum VarClassRequired {
9798 VarClassRequiredAny,
9799 VarClassRequiredConst,
9800 VarClassRequiredIllegal,
9801};
9802
9803static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
9804 switch (type_entry->id) {
9805 case TypeTableEntryIdInvalid:
9806 zig_unreachable();
9807 case TypeTableEntryIdUnreachable:
9808 case TypeTableEntryIdVar:
9809 return VarClassRequiredIllegal;
9810 case TypeTableEntryIdBool:
9811 case TypeTableEntryIdInt:
9812 case TypeTableEntryIdFloat:
9813 case TypeTableEntryIdVoid:
9814 case TypeTableEntryIdPureError:
9815 case TypeTableEntryIdFn:
9816 case TypeTableEntryIdEnumTag:
9817 return VarClassRequiredAny;
9818 case TypeTableEntryIdNumLitFloat:
9819 case TypeTableEntryIdNumLitInt:
9820 case TypeTableEntryIdUndefLit:
9821 case TypeTableEntryIdBlock:
9822 case TypeTableEntryIdNullLit:
9823 case TypeTableEntryIdOpaque:
9824 case TypeTableEntryIdMetaType:
9825 case TypeTableEntryIdNamespace:
9826 case TypeTableEntryIdBoundFn:
9827 case TypeTableEntryIdArgTuple:
9828 return VarClassRequiredConst;
9829
9830 case TypeTableEntryIdPointer:
9831 return get_var_class_required(type_entry->data.pointer.child_type);
9832 case TypeTableEntryIdArray:
9833 return get_var_class_required(type_entry->data.array.child_type);
9834 case TypeTableEntryIdMaybe:
9835 return get_var_class_required(type_entry->data.maybe.child_type);
9836 case TypeTableEntryIdErrorUnion:
9837 return get_var_class_required(type_entry->data.error.child_type);
9838
9839 case TypeTableEntryIdStruct:
9840 case TypeTableEntryIdEnum:
9841 case TypeTableEntryIdUnion:
9842 // TODO check the fields of these things and make sure that they don't recursively
9843 // contain any of the other variable classes
9844 return VarClassRequiredAny;
9845 }
9846 zig_unreachable();
9847}
9848
97979849static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
97989850 VariableTableEntry *var = decl_var_instruction->var;
97999851
......@@ -9803,10 +9855,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
98039855 return var->value->type;
98049856 }
98059857
9806 AstNodeVariableDeclaration *variable_declaration = &var->decl_node->data.variable_declaration;
9807 bool is_export = (variable_declaration->visib_mod == VisibModExport);
9808 bool is_extern = variable_declaration->is_extern;
9809
98109858 var->ref_count = 0;
98119859
98129860 TypeTableEntry *explicit_type = nullptr;
......@@ -9824,59 +9872,30 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
98249872 AstNode *source_node = decl_var_instruction->base.source_node;
98259873
98269874 IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
9875 bool is_comptime_var = ir_get_var_is_comptime(var);
9876
98279877 TypeTableEntry *result_type = casted_init_value->value.type;
98289878 if (type_is_invalid(result_type)) {
98299879 result_type = ira->codegen->builtin_types.entry_invalid;
9830 }
9831
9832 bool is_comptime_var = ir_get_var_is_comptime(var);
9833
9834 switch (result_type->id) {
9835 case TypeTableEntryIdInvalid:
9836 break; // handled above
9837 case TypeTableEntryIdNumLitFloat:
9838 case TypeTableEntryIdNumLitInt:
9839 case TypeTableEntryIdUndefLit:
9840 if (is_export || is_extern || (!var->src_is_const && !is_comptime_var)) {
9841 ir_add_error_node(ira, source_node, buf_sprintf("unable to infer variable type"));
9842 result_type = ira->codegen->builtin_types.entry_invalid;
9843 }
9844 break;
9845 case TypeTableEntryIdUnreachable:
9846 case TypeTableEntryIdVar:
9847 case TypeTableEntryIdBlock:
9848 case TypeTableEntryIdNullLit:
9849 case TypeTableEntryIdOpaque:
9850 ir_add_error_node(ira, source_node,
9851 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
9852 result_type = ira->codegen->builtin_types.entry_invalid;
9853 break;
9854 case TypeTableEntryIdMetaType:
9855 case TypeTableEntryIdNamespace:
9856 if (casted_init_value->value.special == ConstValSpecialRuntime) {
9880 } else {
9881 switch (get_var_class_required(result_type)) {
9882 case VarClassRequiredIllegal:
98579883 ir_add_error_node(ira, source_node,
9858 buf_sprintf("variable of type '%s' must be constant", buf_ptr(&result_type->name)));
9884 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
98599885 result_type = ira->codegen->builtin_types.entry_invalid;
9860 }
9861 break;
9862 case TypeTableEntryIdVoid:
9863 case TypeTableEntryIdBool:
9864 case TypeTableEntryIdInt:
9865 case TypeTableEntryIdFloat:
9866 case TypeTableEntryIdPointer:
9867 case TypeTableEntryIdArray:
9868 case TypeTableEntryIdStruct:
9869 case TypeTableEntryIdMaybe:
9870 case TypeTableEntryIdErrorUnion:
9871 case TypeTableEntryIdPureError:
9872 case TypeTableEntryIdEnum:
9873 case TypeTableEntryIdUnion:
9874 case TypeTableEntryIdFn:
9875 case TypeTableEntryIdBoundFn:
9876 case TypeTableEntryIdEnumTag:
9877 case TypeTableEntryIdArgTuple:
9878 // OK
9879 break;
9886 break;
9887 case VarClassRequiredConst:
9888 if (!var->src_is_const && !is_comptime_var) {
9889 ir_add_error_node(ira, source_node,
9890 buf_sprintf("variable of type '%s' must be const or comptime",
9891 buf_ptr(&result_type->name)));
9892 result_type = ira->codegen->builtin_types.entry_invalid;
9893 }
9894 break;
9895 case VarClassRequiredAny:
9896 // OK
9897 break;
9898 }
98809899 }
98819900
98829901 var->value->type = result_type;
test/compile_errors.zig+36-14
......@@ -1435,20 +1435,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
14351435 \\fn bar() -> %i32 { 0 }
14361436 , ".tmp_source.zig:2:14: error: expression value is ignored");
14371437
1438 cases.add("integer literal on a non-comptime var",
1439 \\export fn foo() {
1440 \\ var i = 0;
1441 \\ while (i < 10) : (i += 1) { }
1442 \\}
1443 , ".tmp_source.zig:2:5: error: unable to infer variable type");
1444
1445 cases.add("undefined literal on a non-comptime var",
1446 \\export fn foo() {
1447 \\ var i = undefined;
1448 \\ i = i32(1);
1449 \\}
1450 , ".tmp_source.zig:2:5: error: unable to infer variable type");
1451
14521438 cases.add("dereference an array",
14531439 \\var s_buffer: [10]u8 = undefined;
14541440 \\pub fn pass(in: []u8) -> []u8 {
......@@ -2090,4 +2076,40 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
20902076 ,
20912077 ".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'");
20922078
2079 cases.add("non-const variables of things that require const variables",
2080 \\const Opaque = @OpaqueType();
2081 \\
2082 \\export fn entry(opaque: &Opaque) {
2083 \\ var m2 = &2;
2084 \\ const y: u32 = *m2;
2085 \\
2086 \\ var a = undefined;
2087 \\ var b = 1;
2088 \\ var c = 1.0;
2089 \\ var d = this;
2090 \\ var e = null;
2091 \\ var f = *opaque;
2092 \\ var g = i32;
2093 \\ var h = @import("std");
2094 \\ var i = (Foo {}).bar;
2095 \\
2096 \\ var z: noreturn = return;
2097 \\}
2098 \\
2099 \\const Foo = struct {
2100 \\ fn bar(self: &const Foo) {}
2101 \\};
2102 ,
2103 ".tmp_source.zig:4:4: error: variable of type '&const (integer literal)' must be const or comptime",
2104 ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
2105 ".tmp_source.zig:8:4: error: variable of type '(integer literal)' must be const or comptime",
2106 ".tmp_source.zig:9:4: error: variable of type '(float literal)' must be const or comptime",
2107 ".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime",
2108 ".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",
2109 ".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime",
2110 ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime",
2111 ".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime",
2112 ".tmp_source.zig:15:4: error: variable of type '(bound fn(&const Foo))' must be const or comptime",
2113 ".tmp_source.zig:17:4: error: unreachable code");
2114
20932115}