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...@@ -3366,9 +3366,12 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
3366 g->tld_ref_source_node_stack.pop();3366 g->tld_ref_source_node_stack.pop();
3367}3367}
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
3370 if (expected_type == actual_type)3373 if (expected_type == actual_type)
3371 return true;3374 return result;
33723375
3373 // pointer const3376 // pointer const
3374 if (expected_type->id == TypeTableEntryIdPointer &&3377 if (expected_type->id == TypeTableEntryIdPointer &&
...@@ -3379,15 +3382,18 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type...@@ -3379,15 +3382,18 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
3379 actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&3382 actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
3380 actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)3383 actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
3381 {3384 {
3382 return types_match_const_cast_only(g, expected_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);
3383 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;
3384 }3392 }
33853393
3386 // slice const3394 // slice const
3387 if (expected_type->id == TypeTableEntryIdStruct &&3395 if (expected_type->id == TypeTableEntryIdStruct && actual_type->id == TypeTableEntryIdStruct &&
3388 actual_type->id == TypeTableEntryIdStruct &&3396 expected_type->data.structure.is_slice && actual_type->data.structure.is_slice)
3389 expected_type->data.structure.is_slice &&
3390 actual_type->data.structure.is_slice)
3391 {3397 {
3392 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;3398 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
3393 TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;3399 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...@@ -3397,43 +3403,54 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
3397 actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&3403 actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
3398 actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)3404 actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
3399 {3405 {
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,
3401 actual_ptr_type->data.pointer.child_type);3407 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;
3402 }3414 }
3403 }3415 }
34043416
3405 // maybe3417 // maybe
3406 if (expected_type->id == TypeTableEntryIdMaybe &&3418 if (expected_type->id == TypeTableEntryIdMaybe && actual_type->id == TypeTableEntryIdMaybe) {
3407 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);
3408 {3420 if (child.id != ConstCastResultIdOk) {
3409 return types_match_const_cast_only(g,3421 result.id = ConstCastResultIdNullableChild;
3410 expected_type->data.maybe.child_type,3422 result.data.nullable_child = allocate_nonzero<ConstCastOnly>(1);
3411 actual_type->data.maybe.child_type);3423 *result.data.nullable_child = child;
3424 }
3425 return result;
3412 }3426 }
34133427
3414 // error union3428 // error union
3415 if (expected_type->id == TypeTableEntryIdErrorUnion &&3429 if (expected_type->id == TypeTableEntryIdErrorUnion && actual_type->id == TypeTableEntryIdErrorUnion) {
3416 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);
3417 {3431 if (payload_child.id != ConstCastResultIdOk) {
3418 return types_match_const_cast_only(g,3432 result.id = ConstCastResultIdErrorUnionPayload;
3419 expected_type->data.error_union.payload_type,3433 result.data.error_union_payload = allocate_nonzero<ConstCastOnly>(1);
3420 actual_type->data.error_union.payload_type) &&3434 *result.data.error_union_payload = payload_child;
3421 types_match_const_cast_only(g,3435 return result;
3422 expected_type->data.error_union.err_set_type,3436 }
3423 actual_type->data.error_union.err_set_type);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;
3424 }3445 }
34253446
3426 // error set3447 // error set
3427 if (expected_type->id == TypeTableEntryIdErrorSet &&3448 if (expected_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdErrorSet) {
3428 actual_type->id == TypeTableEntryIdErrorSet)
3429 {
3430 TypeTableEntry *contained_set = actual_type;3449 TypeTableEntry *contained_set = actual_type;
3431 TypeTableEntry *container_set = expected_type;3450 TypeTableEntry *container_set = expected_type;
34323451
3433 if (container_set == g->builtin_types.entry_global_error_set ||3452 if (container_set == g->builtin_types.entry_global_error_set || container_set->data.error_set.infer_fn != nullptr) {
3434 container_set->data.error_set.infer_fn != nullptr)3453 return result;
3435 {
3436 return true;
3437 }3454 }
34383455
3439 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(g->errors_by_index.length);3456 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...@@ -3445,11 +3462,14 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
3445 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];3462 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
3446 ErrorTableEntry *error_entry = errors[contained_error_entry->value];3463 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
3447 if (error_entry == nullptr) {3464 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);
3449 }3469 }
3450 }3470 }
3451 free(errors);3471 free(errors);
3452 return true;3472 return result;
3453 }3473 }
34543474
3455 // fn3475 // fn
...@@ -3457,30 +3477,39 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type...@@ -3457,30 +3477,39 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
3457 actual_type->id == TypeTableEntryIdFn)3477 actual_type->id == TypeTableEntryIdFn)
3458 {3478 {
3459 if (expected_type->data.fn.fn_type_id.alignment > actual_type->data.fn.fn_type_id.alignment) {3479 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;
3461 }3482 }
3462 if (expected_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {3483 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;
3464 }3486 }
3465 if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {3487 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;
3467 }3490 }
3468 if (expected_type->data.fn.is_generic != actual_type->data.fn.is_generic) {3491 if (expected_type->data.fn.is_generic != actual_type->data.fn.is_generic) {
3469 return false;3492 result.id = ConstCastResultIdFnIsGeneric;
3493 return result;
3470 }3494 }
3471 if (!expected_type->data.fn.is_generic &&3495 if (!expected_type->data.fn.is_generic &&
3472 actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable &&3496 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))
3476 {3497 {
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;
3478 }3505 }
3479 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {3506 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;
3481 }3509 }
3482 if (expected_type->data.fn.fn_type_id.next_param_index != actual_type->data.fn.fn_type_id.next_param_index) {3510 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;
3484 }3513 }
3485 assert(expected_type->data.fn.is_generic ||3514 assert(expected_type->data.fn.is_generic ||
3486 expected_type->data.fn.fn_type_id.next_param_index == expected_type->data.fn.fn_type_id.param_count);3515 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...@@ -3489,19 +3518,26 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
3489 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];3518 FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
3490 FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];3519 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)) {3521 ConstCastOnly arg_child = types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type);
3493 return false;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;
3494 }3528 }
34953529
3496 if (expected_param_info->is_noalias != actual_param_info->is_noalias) {3530 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;
3498 }3534 }
3499 }3535 }
3500 return true;3536 return result;
3501 }3537 }
35023538
35033539 result.id = ConstCastResultIdType;
3504 return false;3540 return result;
3505}3541}
35063542
3507Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {3543Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
src/analyze.hpp+50-1
...@@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry);...@@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry);
46ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);46ImportTableEntry *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);
50VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);49VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
51Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);50Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
52void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);51void 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);...@@ -191,4 +190,54 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
191190
192TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);191TypeTableEntry *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
194#endif243#endif
src/ir.cpp+6-4
...@@ -6428,6 +6428,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -6428,6 +6428,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
6428 return ImplicitCastMatchResultYes;6428 return ImplicitCastMatchResultYes;
6429 }6429 }
64306430
6431 // if we got here with error sets, make an error showing the incompatibilities
6432 if (expected_typek
6433
6431 // implicit conversion from anything to var6434 // implicit conversion from anything to var
6432 if (expected_type->id == TypeTableEntryIdVar) {6435 if (expected_type->id == TypeTableEntryIdVar) {
6433 return ImplicitCastMatchResultYes;6436 return ImplicitCastMatchResultYes;
...@@ -6801,9 +6804,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -6801,9 +6804,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
6801 errors[error_entry->value] = error_entry;6804 errors[error_entry->value] = error_entry;
6802 }6805 }
6803 continue;6806 continue;
6804 }6807 } else {
6805 if (prev_type->id == TypeTableEntryIdErrorUnion) {6808 // check if the cur type error set is a subset
6806 // check if the cur type error set must be a subset
6807 bool prev_is_superset = true;6809 bool prev_is_superset = true;
6808 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {6810 for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
6809 ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];6811 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...@@ -8471,7 +8473,7 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
8471 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);8473 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
8472 switch (result) {8474 switch (result) {
8473 case ImplicitCastMatchResultNo:8475 case ImplicitCastMatchResultNo:
8474 ir_add_error(ira, value,8476 ErrorMsg *msg = ir_add_error(ira, value,
8475 buf_sprintf("expected type '%s', found '%s'",8477 buf_sprintf("expected type '%s', found '%s'",
8476 buf_ptr(&expected_type->name),8478 buf_ptr(&expected_type->name),
8477 buf_ptr(&value->value.type->name)));8479 buf_ptr(&value->value.type->name)));