mirror of
https://github.com/ziglang/zig.git
synced 2025-12-22 14:13:08 +00:00
*WIP* error sets - rewrite "const cast only" function
This commit is contained in:
parent
406496ca33
commit
cfb2c67692
136
src/analyze.cpp
136
src/analyze.cpp
@ -3366,9 +3366,12 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
|
|||||||
g->tld_ref_source_node_stack.pop();
|
g->tld_ref_source_node_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
|
ConstCastOnly types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
|
||||||
|
ConstCastOnly result = {0};
|
||||||
|
result.id = ConstCastResultIdOk;
|
||||||
|
|
||||||
if (expected_type == actual_type)
|
if (expected_type == actual_type)
|
||||||
return true;
|
return result;
|
||||||
|
|
||||||
// pointer const
|
// pointer const
|
||||||
if (expected_type->id == TypeTableEntryIdPointer &&
|
if (expected_type->id == TypeTableEntryIdPointer &&
|
||||||
@ -3379,15 +3382,18 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
|
|||||||
actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
|
actual_type->data.pointer.unaligned_bit_count == expected_type->data.pointer.unaligned_bit_count &&
|
||||||
actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
|
actual_type->data.pointer.alignment >= expected_type->data.pointer.alignment)
|
||||||
{
|
{
|
||||||
return types_match_const_cast_only(g, expected_type->data.pointer.child_type,
|
ConstCastOnly child = types_match_const_cast_only(g, expected_type->data.pointer.child_type, actual_type->data.pointer.child_type);
|
||||||
actual_type->data.pointer.child_type);
|
if (child.id != ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdPointerChild;
|
||||||
|
result.data.pointer_child = allocate_nonzero<ConstCastOnly>(1);
|
||||||
|
*result.data.pointer_child = child;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// slice const
|
// slice const
|
||||||
if (expected_type->id == TypeTableEntryIdStruct &&
|
if (expected_type->id == TypeTableEntryIdStruct && actual_type->id == TypeTableEntryIdStruct &&
|
||||||
actual_type->id == TypeTableEntryIdStruct &&
|
expected_type->data.structure.is_slice && actual_type->data.structure.is_slice)
|
||||||
expected_type->data.structure.is_slice &&
|
|
||||||
actual_type->data.structure.is_slice)
|
|
||||||
{
|
{
|
||||||
TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
|
TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||||
TypeTableEntry *expected_ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry;
|
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
|
|||||||
actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
|
actual_ptr_type->data.pointer.unaligned_bit_count == expected_ptr_type->data.pointer.unaligned_bit_count &&
|
||||||
actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
|
actual_ptr_type->data.pointer.alignment >= expected_ptr_type->data.pointer.alignment)
|
||||||
{
|
{
|
||||||
return types_match_const_cast_only(g, expected_ptr_type->data.pointer.child_type,
|
ConstCastOnly child = types_match_const_cast_only(g, expected_ptr_type->data.pointer.child_type,
|
||||||
actual_ptr_type->data.pointer.child_type);
|
actual_ptr_type->data.pointer.child_type);
|
||||||
|
if (child.id != ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdSliceChild;
|
||||||
|
result.data.slice_child = allocate_nonzero<ConstCastOnly>(1);
|
||||||
|
*result.data.slice_child = child;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe
|
// maybe
|
||||||
if (expected_type->id == TypeTableEntryIdMaybe &&
|
if (expected_type->id == TypeTableEntryIdMaybe && actual_type->id == TypeTableEntryIdMaybe) {
|
||||||
actual_type->id == TypeTableEntryIdMaybe)
|
ConstCastOnly child = types_match_const_cast_only(g, expected_type->data.maybe.child_type, actual_type->data.maybe.child_type);
|
||||||
{
|
if (child.id != ConstCastResultIdOk) {
|
||||||
return types_match_const_cast_only(g,
|
result.id = ConstCastResultIdNullableChild;
|
||||||
expected_type->data.maybe.child_type,
|
result.data.nullable_child = allocate_nonzero<ConstCastOnly>(1);
|
||||||
actual_type->data.maybe.child_type);
|
*result.data.nullable_child = child;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// error union
|
// error union
|
||||||
if (expected_type->id == TypeTableEntryIdErrorUnion &&
|
if (expected_type->id == TypeTableEntryIdErrorUnion && actual_type->id == TypeTableEntryIdErrorUnion) {
|
||||||
actual_type->id == TypeTableEntryIdErrorUnion)
|
ConstCastOnly payload_child = types_match_const_cast_only(g, expected_type->data.error_union.payload_type, actual_type->data.error_union.payload_type);
|
||||||
{
|
if (payload_child.id != ConstCastResultIdOk) {
|
||||||
return types_match_const_cast_only(g,
|
result.id = ConstCastResultIdErrorUnionPayload;
|
||||||
expected_type->data.error_union.payload_type,
|
result.data.error_union_payload = allocate_nonzero<ConstCastOnly>(1);
|
||||||
actual_type->data.error_union.payload_type) &&
|
*result.data.error_union_payload = payload_child;
|
||||||
types_match_const_cast_only(g,
|
return result;
|
||||||
expected_type->data.error_union.err_set_type,
|
}
|
||||||
actual_type->data.error_union.err_set_type);
|
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);
|
||||||
|
if (error_set_child.id != ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdErrorUnionErrorSet;
|
||||||
|
result.data.error_union_error_set = allocate_nonzero<ConstCastOnly>(1);
|
||||||
|
*result.data.error_union_error_set = error_set_child;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// error set
|
// error set
|
||||||
if (expected_type->id == TypeTableEntryIdErrorSet &&
|
if (expected_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdErrorSet) {
|
||||||
actual_type->id == TypeTableEntryIdErrorSet)
|
|
||||||
{
|
|
||||||
TypeTableEntry *contained_set = actual_type;
|
TypeTableEntry *contained_set = actual_type;
|
||||||
TypeTableEntry *container_set = expected_type;
|
TypeTableEntry *container_set = expected_type;
|
||||||
|
|
||||||
if (container_set == g->builtin_types.entry_global_error_set ||
|
if (container_set == g->builtin_types.entry_global_error_set || container_set->data.error_set.infer_fn != nullptr) {
|
||||||
container_set->data.error_set.infer_fn != nullptr)
|
return result;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorTableEntry **errors = allocate<ErrorTableEntry *>(g->errors_by_index.length);
|
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
|
|||||||
ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
|
ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
|
||||||
ErrorTableEntry *error_entry = errors[contained_error_entry->value];
|
ErrorTableEntry *error_entry = errors[contained_error_entry->value];
|
||||||
if (error_entry == nullptr) {
|
if (error_entry == nullptr) {
|
||||||
return false;
|
if (result.id == ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdErrSet;
|
||||||
|
}
|
||||||
|
result.data.error_set.errors.append(contained_error_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(errors);
|
free(errors);
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn
|
// fn
|
||||||
@ -3457,30 +3477,39 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
|
|||||||
actual_type->id == TypeTableEntryIdFn)
|
actual_type->id == TypeTableEntryIdFn)
|
||||||
{
|
{
|
||||||
if (expected_type->data.fn.fn_type_id.alignment > actual_type->data.fn.fn_type_id.alignment) {
|
if (expected_type->data.fn.fn_type_id.alignment > actual_type->data.fn.fn_type_id.alignment) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnAlign;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (expected_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
|
if (expected_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnCC;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
|
if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnVarArgs;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (expected_type->data.fn.is_generic != actual_type->data.fn.is_generic) {
|
if (expected_type->data.fn.is_generic != actual_type->data.fn.is_generic) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnIsGeneric;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (!expected_type->data.fn.is_generic &&
|
if (!expected_type->data.fn.is_generic &&
|
||||||
actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable &&
|
actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable)
|
||||||
!types_match_const_cast_only(g,
|
|
||||||
expected_type->data.fn.fn_type_id.return_type,
|
|
||||||
actual_type->data.fn.fn_type_id.return_type))
|
|
||||||
{
|
{
|
||||||
return false;
|
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);
|
||||||
|
if (child.id != ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdFnReturnType;
|
||||||
|
result.data.return_type = allocate_nonzero<ConstCastOnly>(1);
|
||||||
|
*result.data.return_type = child;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
|
if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnArgCount;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (expected_type->data.fn.fn_type_id.next_param_index != actual_type->data.fn.fn_type_id.next_param_index) {
|
if (expected_type->data.fn.fn_type_id.next_param_index != actual_type->data.fn.fn_type_id.next_param_index) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnGenericArgCount;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
assert(expected_type->data.fn.is_generic ||
|
assert(expected_type->data.fn.is_generic ||
|
||||||
expected_type->data.fn.fn_type_id.next_param_index == expected_type->data.fn.fn_type_id.param_count);
|
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
|
|||||||
FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
|
FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
|
||||||
FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
|
FnTypeParamInfo *expected_param_info = &expected_type->data.fn.fn_type_id.param_info[i];
|
||||||
|
|
||||||
if (!types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type)) {
|
ConstCastOnly arg_child = types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type);
|
||||||
return false;
|
if (arg_child.id != ConstCastResultIdOk) {
|
||||||
|
result.id = ConstCastResultIdFnArg;
|
||||||
|
result.data.fn_arg.arg_index = i;
|
||||||
|
result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1);
|
||||||
|
*result.data.fn_arg.child = arg_child;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expected_param_info->is_noalias != actual_param_info->is_noalias) {
|
if (expected_param_info->is_noalias != actual_param_info->is_noalias) {
|
||||||
return false;
|
result.id = ConstCastResultIdFnArgNoAlias;
|
||||||
|
result.data.arg_no_alias.arg_index = i;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.id = ConstCastResultIdType;
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
|
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
|
||||||
|
|||||||
@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry);
|
|||||||
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
|
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
|
||||||
|
|
||||||
|
|
||||||
bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
|
|
||||||
VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
|
VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
|
||||||
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
|
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
|
||||||
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
|
void 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);
|
|||||||
|
|
||||||
TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
|
TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
|
||||||
|
|
||||||
|
enum ConstCastResultId {
|
||||||
|
ConstCastResultIdOk,
|
||||||
|
ConstCastResultIdErrSet,
|
||||||
|
ConstCastResultIdPointerChild,
|
||||||
|
ConstCastResultIdSliceChild,
|
||||||
|
ConstCastResultIdNullableChild,
|
||||||
|
ConstCastResultIdErrorUnionPayload,
|
||||||
|
ConstCastResultIdErrorUnionErrorSet,
|
||||||
|
ConstCastResultIdFnAlign,
|
||||||
|
ConstCastResultIdFnCC,
|
||||||
|
ConstCastResultIdFnVarArgs,
|
||||||
|
ConstCastResultIdFnIsGeneric,
|
||||||
|
ConstCastResultIdFnReturnType,
|
||||||
|
ConstCastResultIdFnArgCount,
|
||||||
|
ConstCastResultIdFnGenericArgCount,
|
||||||
|
ConstCastResultIdFnArg,
|
||||||
|
ConstCastResultIdFnArgNoAlias,
|
||||||
|
ConstCastResultIdType,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstCastErrSetMismatch {
|
||||||
|
ZigList<ErrorTableEntry *> missing_errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstCastArg {
|
||||||
|
size_t arg_index;
|
||||||
|
ConstCastOnly *child;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstCastArgNoAlias {
|
||||||
|
size_t arg_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstCastOnly {
|
||||||
|
ConstCastResultId id;
|
||||||
|
union {
|
||||||
|
ConstCastErrSetMismatch error_set;
|
||||||
|
ConstCastOnly *pointer_child;
|
||||||
|
ConstCastOnly *slice_child;
|
||||||
|
ConstCastOnly *nullable_child;
|
||||||
|
ConstCastOnly *error_union_payload;
|
||||||
|
ConstCastOnly *error_union_error_set;
|
||||||
|
ConstCastOnly *return_type;
|
||||||
|
ConstCastArg fn_arg;
|
||||||
|
ConstCastArgNoAlias arg_no_alias;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
src/ir.cpp
10
src/ir.cpp
@ -6428,6 +6428,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
|||||||
return ImplicitCastMatchResultYes;
|
return ImplicitCastMatchResultYes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we got here with error sets, make an error showing the incompatibilities
|
||||||
|
if (expected_typek
|
||||||
|
|
||||||
// implicit conversion from anything to var
|
// implicit conversion from anything to var
|
||||||
if (expected_type->id == TypeTableEntryIdVar) {
|
if (expected_type->id == TypeTableEntryIdVar) {
|
||||||
return ImplicitCastMatchResultYes;
|
return ImplicitCastMatchResultYes;
|
||||||
@ -6801,9 +6804,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
|||||||
errors[error_entry->value] = error_entry;
|
errors[error_entry->value] = error_entry;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
if (prev_type->id == TypeTableEntryIdErrorUnion) {
|
// check if the cur type error set is a subset
|
||||||
// check if the cur type error set must be a subset
|
|
||||||
bool prev_is_superset = true;
|
bool prev_is_superset = true;
|
||||||
for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
|
for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) {
|
||||||
ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i];
|
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
|
|||||||
ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
|
ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->value.type, value);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case ImplicitCastMatchResultNo:
|
case ImplicitCastMatchResultNo:
|
||||||
ir_add_error(ira, value,
|
ErrorMsg *msg = ir_add_error(ira, value,
|
||||||
buf_sprintf("expected type '%s', found '%s'",
|
buf_sprintf("expected type '%s', found '%s'",
|
||||||
buf_ptr(&expected_type->name),
|
buf_ptr(&expected_type->name),
|
||||||
buf_ptr(&value->value.type->name)));
|
buf_ptr(&value->value.type->name)));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user