authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-24 12:09:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-24 12:09:51-07:00
log8ad75a9bf3a7fa9782bf17165fa6d7dc842efb51
tree342f75149314e8505eb5a85decd675e0731d6921
parent46ab981787a108ad4326c86aa2a6af4247e7191b

add compile error for invalid equality operator uses

See #145

2 files changed, 60 insertions(+), 13 deletions(-)

src/analyze.cpp+45-13
...@@ -3014,20 +3014,52 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im...@@ -3014,20 +3014,52 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
3014 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,3014 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
3015 op_nodes, op_types, 2);3015 op_nodes, op_types, 2);
30163016
3017 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||3017 bool is_equality_cmp = (bin_op_type == BinOpTypeCmpEq || bin_op_type == BinOpTypeCmpNotEq);
3018 resolved_type->id == TypeTableEntryIdNumLitInt ||
3019 resolved_type->id == TypeTableEntryIdFloat ||
3020 resolved_type->id == TypeTableEntryIdInt);
30213018
3022 if (resolved_type->id == TypeTableEntryIdInvalid) {3019 switch (resolved_type->id) {
3023 return g->builtin_types.entry_invalid;3020 case TypeTableEntryIdInvalid:
3024 } else if (bin_op_type != BinOpTypeCmpEq &&3021 return g->builtin_types.entry_invalid;
3025 bin_op_type != BinOpTypeCmpNotEq &&3022
3026 !type_can_gt_lt_cmp)3023 case TypeTableEntryIdNumLitFloat:
3027 {3024 case TypeTableEntryIdNumLitInt:
3028 add_node_error(g, node,3025 case TypeTableEntryIdInt:
3029 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));3026 case TypeTableEntryIdFloat:
3030 return g->builtin_types.entry_invalid;3027 break;
3028
3029 case TypeTableEntryIdBool:
3030 case TypeTableEntryIdMetaType:
3031 case TypeTableEntryIdVoid:
3032 case TypeTableEntryIdPointer:
3033 case TypeTableEntryIdPureError:
3034 case TypeTableEntryIdFn:
3035 case TypeTableEntryIdTypeDecl:
3036 case TypeTableEntryIdNamespace:
3037 case TypeTableEntryIdGenericFn:
3038 if (!is_equality_cmp) {
3039 add_node_error(g, node,
3040 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3041 return g->builtin_types.entry_invalid;
3042 }
3043 break;
3044
3045 case TypeTableEntryIdEnum:
3046 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
3047 add_node_error(g, node,
3048 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3049 return g->builtin_types.entry_invalid;
3050 }
3051 break;
3052
3053 case TypeTableEntryIdUnreachable:
3054 case TypeTableEntryIdArray:
3055 case TypeTableEntryIdStruct:
3056 case TypeTableEntryIdUndefLit:
3057 case TypeTableEntryIdMaybe:
3058 case TypeTableEntryIdErrorUnion:
3059 case TypeTableEntryIdUnion:
3060 add_node_error(g, node,
3061 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3062 return g->builtin_types.entry_invalid;
3031 }3063 }
30323064
3033 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;3065 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
test/run_tests.cpp+15
...@@ -1218,6 +1218,21 @@ fn test_a_thing() {...@@ -1218,6 +1218,21 @@ fn test_a_thing() {
1218 bad_fn_call();1218 bad_fn_call();
1219}1219}
1220 )SOURCE", 1, ".tmp_source.zig:6:5: error: use of undeclared identifier 'bad_fn_call'");1220 )SOURCE", 1, ".tmp_source.zig:6:5: error: use of undeclared identifier 'bad_fn_call'");
1221
1222 add_compile_fail_case("illegal comparison of types", R"SOURCE(
1223fn bad_eql_1(a: []u8, b: []u8) -> bool {
1224 a == b
1225}
1226enum EnumWithData {
1227 One,
1228 Two: i32,
1229}
1230fn bad_eql_2(a: EnumWithData, b: EnumWithData) -> bool {
1231 a == b
1232}
1233 )SOURCE", 2,
1234 ".tmp_source.zig:3:7: error: operator not allowed for type '[]u8'",
1235 ".tmp_source.zig:10:7: error: operator not allowed for type 'EnumWithData'");
1221}1236}
12221237
1223//////////////////////////////////////////////////////////////////////////////1238//////////////////////////////////////////////////////////////////////////////