authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-02 11:50:19-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-02 11:50:19-05:00
logcfb2c676925d77887e46631dcafa783e6c65e61d
tree15b2f7613e0ebb382d5e5c3527d27cf94e458c80
parent406496ca3371b7f50aee141fa37c52e86d96783f

*WIP* error sets - rewrite "const cast only" function


3 files changed, 142 insertions(+), 55 deletions(-)

src/analyze.cpp+86-50
......@@ -3366,9 +3366,12 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
33663366 g->tld_ref_source_node_stack.pop();
33673367}
33683368
3369bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
3369ConstCastOnly types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
3370 ConstCastOnly result = {0};
3371 result.id = ConstCastResultIdOk;
3372
33703373 if (expected_type == actual_type)
3371 return true;
3374 return result;
33723375
33733376 // pointer const
33743377 if (expected_type->id == TypeTableEntryIdPointer &&
......@@ -3379,15 +3382,18 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
33793382 actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
33803383 actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
33813384 {
3382 return types_match_const_cast_only(g, expected_type->data.pointer.child_type,
3383 actual_type->data.pointer.child_type);
3385 ConstCastOnly child = types_match_const_cast_only(g, expected_type->data.pointer.child_type, actual_type->data.pointer.child_type);
3386 if (child.id != ConstCastResultIdOk) {
3387 result.id = ConstCastResultIdPointerChild;
3388 result.data.pointer_child = allocate_nonzero<ConstCastOnly>(1);
3389 *result.data.pointer_child = child;
3390 }
3391 return result;
33843392 }
33853393
33863394 // slice const
3387 if (expected_type->id == TypeTableEntryIdStruct &&
3388 actual_type->id == TypeTableEntryIdStruct &&
3389 expected_type->data.structure.is_slice &&
3390 actual_type->data.structure.is_slice)
3395 if (expected_type->id == TypeTableEntryIdStruct && actual_type->id == TypeTableEntryIdStruct &&
3396 expected_type->data.structure.is_slice && actual_type->data.structure.is_slice)
33913397 {
33923398 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
33933399 TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
......@@ -3397,43 +3403,54 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
33973403 actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
33983404 actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
33993405 {
3400 return types_match_const_cast_only(g, expected_ptr_type->data.pointer.child_type,
3406 ConstCastOnly child = types_match_const_cast_only(g, expected_ptr_type->data.pointer.child_type,
34013407 actual_ptr_type->data.pointer.child_type);
3408 if (child.id != ConstCastResultIdOk) {
3409 result.id = ConstCastResultIdSliceChild;
3410 result.data.slice_child = allocate_nonzero<ConstCastOnly>(1);
3411 *result.data.slice_child = child;
3412 }
3413 return result;
34023414 }
34033415 }
34043416
34053417 // maybe
3406 if (expected_type->id == TypeTableEntryIdMaybe &&
3407 actual_type->id == TypeTableEntryIdMaybe)
3408 {
3409 return types_match_const_cast_only(g,
3410 expected_type->data.maybe.child_type,
3411 actual_type->data.maybe.child_type);
3418 if (expected_type->id == TypeTableEntryIdMaybe && actual_type->id == TypeTableEntryIdMaybe) {
3419 ConstCastOnly child = types_match_const_cast_only(g, expected_type->data.maybe.child_type, actual_type->data.maybe.child_type);
3420 if (child.id != ConstCastResultIdOk) {
3421 result.id = ConstCastResultIdNullableChild;
3422 result.data.nullable_child = allocate_nonzero<ConstCastOnly>(1);
3423 *result.data.nullable_child = child;
3424 }
3425 return result;
34123426 }
34133427
34143428 // error union
3415 if (expected_type->id == TypeTableEntryIdErrorUnion &&
3416 actual_type->id == TypeTableEntryIdErrorUnion)
3417 {
3418 return types_match_const_cast_only(g,
3419 expected_type->data.error_union.payload_type,
3420 actual_type->data.error_union.payload_type) &&
3421 types_match_const_cast_only(g,
3422 expected_type->data.error_union.err_set_type,
3423 actual_type->data.error_union.err_set_type);
3429 if (expected_type->id == TypeTableEntryIdErrorUnion && actual_type->id == TypeTableEntryIdErrorUnion) {
3430 ConstCastOnly payload_child = types_match_const_cast_only(g, expected_type->data.error_union.payload_type, actual_type->data.error_union.payload_type);
3431 if (payload_child.id != ConstCastResultIdOk) {
3432 result.id = ConstCastResultIdErrorUnionPayload;
3433 result.data.error_union_payload = allocate_nonzero<ConstCastOnly>(1);
3434 *result.data.error_union_payload = payload_child;
3435 return result;
3436 }
3437 ConstCastOnly error_set_child = types_match_const_cast_only(g, expected_type->data.error_union.err_set_type, actual_type->data.error_union.err_set_type);
3438 if (error_set_child.id != ConstCastResultIdOk) {
3439 result.id = ConstCastResultIdErrorUnionErrorSet;
3440 result.data.error_union_error_set = allocate_nonzero<ConstCastOnly>(1);
3441 *result.data.error_union_error_set = error_set_child;
3442 return result;
3443 }
3444 return result;
34243445 }
34253446
34263447 // error set
3427 if (expected_type->id == TypeTableEntryIdErrorSet &&
3428 actual_type->id == TypeTableEntryIdErrorSet)
3429 {
3448 if (expected_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdErrorSet) {
34303449 TypeTableEntry *contained_set = actual_type;
34313450 TypeTableEntry *container_set = expected_type;
34323451
3433 if (container_set == g->builtin_types.entry_global_error_set ||
3434 container_set->data.error_set.infer_fn != nullptr)
3435 {
3436 return true;
3452 if (container_set == g->builtin_types.entry_global_error_set || container_set->data.error_set.infer_fn != nullptr) {
3453 return result;
34373454 }
34383455
34393456 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(g->errors_by_index.length);
......@@ -3445,11 +3462,14 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
34453462 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
34463463 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
34473464 if (error_entry == nullptr) {
3448 return false;
3465 if (result.id == ConstCastResultIdOk) {
3466 result.id = ConstCastResultIdErrSet;
3467 }
3468 result.data.error_set.errors.append(contained_error_entry);
34493469 }
34503470 }
34513471 free(errors);
3452 return true;
3472 return result;
34533473 }
34543474
34553475 // fn
......@@ -3457,30 +3477,39 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
34573477 actual_type->id == TypeTableEntryIdFn)
34583478 {
34593479 if (expected_type->data.fn.fn_type_id.alignment > actual_type->data.fn.fn_type_id.alignment) {
3460 return false;
3480 result.id = ConstCastResultIdFnAlign;
3481 return result;
34613482 }
34623483 if (expected_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
3463 return false;
3484 result.id = ConstCastResultIdFnCC;
3485 return result;
34643486 }
34653487 if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
3466 return false;
3488 result.id = ConstCastResultIdFnVarArgs;
3489 return result;
34673490 }
34683491 if (expected_type->data.fn.is_generic != actual_type->data.fn.is_generic) {
3469 return false;
3492 result.id = ConstCastResultIdFnIsGeneric;
3493 return result;
34703494 }
34713495 if (!expected_type->data.fn.is_generic &&
3472 actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable &&
3473 !types_match_const_cast_only(g,
3474 expected_type->data.fn.fn_type_id.return_type,
3475 actual_type->data.fn.fn_type_id.return_type))
3496 actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable)
34763497 {
3477 return false;
3498 ConstCastOnly child = types_match_const_cast_only(g, expected_type->data.fn.fn_type_id.return_type, actual_type->data.fn.fn_type_id.return_type);
3499 if (child.id != ConstCastResultIdOk) {
3500 result.id = ConstCastResultIdFnReturnType;
3501 result.data.return_type = allocate_nonzero<ConstCastOnly>(1);
3502 *result.data.return_type = child;
3503 }
3504 return result;
34783505 }
34793506 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
3480 return false;
3507 result.id = ConstCastResultIdFnArgCount;
3508 return result;
34813509 }
34823510 if (expected_type->data.fn.fn_type_id.next_param_index != actual_type->data.fn.fn_type_id.next_param_index) {
3483 return false;
3511 result.id = ConstCastResultIdFnGenericArgCount;
3512 return result;
34843513 }
34853514 assert(expected_type->data.fn.is_generic ||
34863515 expected_type->data.fn.fn_type_id.next_param_index == expected_type->data.fn.fn_type_id.param_count);
......@@ -3489,19 +3518,26 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
34893518 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
34903519 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
34913520
3492 if (!types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type)) {
3493 return false;
3521 ConstCastOnly arg_child = types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type);
3522 if (arg_child.id != ConstCastResultIdOk) {
3523 result.id = ConstCastResultIdFnArg;
3524 result.data.fn_arg.arg_index = i;
3525 result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1);
3526 *result.data.fn_arg.child = arg_child;
3527 return result;
34943528 }
34953529
34963530 if (expected_param_info->is_noalias != actual_param_info->is_noalias) {
3497 return false;
3531 result.id = ConstCastResultIdFnArgNoAlias;
3532 result.data.arg_no_alias.arg_index = i;
3533 return result;
34983534 }
34993535 }
3500 return true;
3536 return result;
35013537 }
35023538
3503
3504 return false;
3539 result.id = ConstCastResultIdType;
3540 return result;
35053541}
35063542
35073543Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
src/analyze.hpp+50-1
......@@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry);
4646ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
4747
4848
49bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
5049VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
5150Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
5251void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
......@@ -191,4 +190,54 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
191190
192191TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
193192
193enum ConstCastResultId {
194 ConstCastResultIdOk,
195 ConstCastResultIdErrSet,
196 ConstCastResultIdPointerChild,
197 ConstCastResultIdSliceChild,
198 ConstCastResultIdNullableChild,
199 ConstCastResultIdErrorUnionPayload,
200 ConstCastResultIdErrorUnionErrorSet,
201 ConstCastResultIdFnAlign,
202 ConstCastResultIdFnCC,
203 ConstCastResultIdFnVarArgs,
204 ConstCastResultIdFnIsGeneric,
205 ConstCastResultIdFnReturnType,
206 ConstCastResultIdFnArgCount,
207 ConstCastResultIdFnGenericArgCount,
208 ConstCastResultIdFnArg,
209 ConstCastResultIdFnArgNoAlias,
210 ConstCastResultIdType,
211};
212
213struct ConstCastErrSetMismatch {
214 ZigList<ErrorTableEntry *> missing_errors;
215};
216
217struct ConstCastArg {
218 size_t arg_index;
219 ConstCastOnly *child;
220};
221
222struct ConstCastArgNoAlias {
223 size_t arg_index;
224};
225
226struct ConstCastOnly {
227 ConstCastResultId id;
228 union {
229 ConstCastErrSetMismatch error_set;
230 ConstCastOnly *pointer_child;
231 ConstCastOnly *slice_child;
232 ConstCastOnly *nullable_child;
233 ConstCastOnly *error_union_payload;
234 ConstCastOnly *error_union_error_set;
235 ConstCastOnly *return_type;
236 ConstCastArg fn_arg;
237 ConstCastArgNoAlias arg_no_alias;
238 } data;
239};
240
241bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
242
194243#endif
src/ir.cpp+6-4
......@@ -6428,6 +6428,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
64286428 return ImplicitCastMatchResultYes;
64296429 }
64306430
6431 // if we got here with error sets, make an error showing the incompatibilities
6432 if (expected_typek
6433
64316434 // implicit conversion from anything to var
64326435 if (expected_type->id == TypeTableEntryIdVar) {
64336436 return ImplicitCastMatchResultYes;
......@@ -6801,9 +6804,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
68016804 errors[error_entry->value] = error_entry;
68026805 }
68036806 continue;
6804 }
6805 if (prev_type->id == TypeTableEntryIdErrorUnion) {
6806 // check if the cur type error set must be a subset
6807 } else {
6808 // check if the cur type error set is a subset
68076809 bool prev_is_superset = true;
68086810 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
68096811 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
......@@ -8471,7 +8473,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
84718473 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
84728474 switch (result) {
84738475 case ImplicitCastMatchResultNo:
8474 ir_add_error(ira, value,
8476 ErrorMsg *msg = ir_add_error(ira, value,
84758477 buf_sprintf("expected type '%s', found '%s'",
84768478 buf_ptr(&expected_type->name),
84778479 buf_ptr(&value->value.type->name)));