Commit cfb2c67692
Changed files (3)
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();
}
-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)
- return true;
+ return result;
// pointer const
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.alignment >= expected_type->data.pointer.alignment)
{
- return types_match_const_cast_only(g, expected_type->data.pointer.child_type,
- actual_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);
+ if (child.id != ConstCastResultIdOk) {
+ result.id = ConstCastResultIdPointerChild;
+ result.data.pointer_child = allocate_nonzero<ConstCastOnly>(1);
+ *result.data.pointer_child = child;
+ }
+ return result;
}
// slice const
- if (expected_type->id == TypeTableEntryIdStruct &&
- actual_type->id == TypeTableEntryIdStruct &&
- expected_type->data.structure.is_slice &&
- actual_type->data.structure.is_slice)
+ if (expected_type->id == TypeTableEntryIdStruct && actual_type->id == TypeTableEntryIdStruct &&
+ 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 *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.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);
+ if (child.id != ConstCastResultIdOk) {
+ result.id = ConstCastResultIdSliceChild;
+ result.data.slice_child = allocate_nonzero<ConstCastOnly>(1);
+ *result.data.slice_child = child;
+ }
+ return result;
}
}
// maybe
- if (expected_type->id == TypeTableEntryIdMaybe &&
- actual_type->id == TypeTableEntryIdMaybe)
- {
- return types_match_const_cast_only(g,
- expected_type->data.maybe.child_type,
- actual_type->data.maybe.child_type);
+ if (expected_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) {
+ result.id = ConstCastResultIdNullableChild;
+ result.data.nullable_child = allocate_nonzero<ConstCastOnly>(1);
+ *result.data.nullable_child = child;
+ }
+ return result;
}
// error union
- if (expected_type->id == TypeTableEntryIdErrorUnion &&
- actual_type->id == TypeTableEntryIdErrorUnion)
- {
- return types_match_const_cast_only(g,
- expected_type->data.error_union.payload_type,
- actual_type->data.error_union.payload_type) &&
- types_match_const_cast_only(g,
- expected_type->data.error_union.err_set_type,
- actual_type->data.error_union.err_set_type);
+ if (expected_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) {
+ result.id = ConstCastResultIdErrorUnionPayload;
+ result.data.error_union_payload = allocate_nonzero<ConstCastOnly>(1);
+ *result.data.error_union_payload = payload_child;
+ return result;
+ }
+ 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
- if (expected_type->id == TypeTableEntryIdErrorSet &&
- actual_type->id == TypeTableEntryIdErrorSet)
- {
+ if (expected_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdErrorSet) {
TypeTableEntry *contained_set = actual_type;
TypeTableEntry *container_set = expected_type;
- if (container_set == g->builtin_types.entry_global_error_set ||
- container_set->data.error_set.infer_fn != nullptr)
- {
- return true;
+ if (container_set == g->builtin_types.entry_global_error_set || container_set->data.error_set.infer_fn != nullptr) {
+ return result;
}
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 *error_entry = errors[contained_error_entry->value];
if (error_entry == nullptr) {
- return false;
+ if (result.id == ConstCastResultIdOk) {
+ result.id = ConstCastResultIdErrSet;
+ }
+ result.data.error_set.errors.append(contained_error_entry);
}
}
free(errors);
- return true;
+ return result;
}
// fn
@@ -3457,30 +3477,39 @@ bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, Type
actual_type->id == TypeTableEntryIdFn)
{
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) {
- 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) {
- return false;
+ result.id = ConstCastResultIdFnVarArgs;
+ return result;
}
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 &&
- 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))
+ actual_type->data.fn.fn_type_id.return_type->id != TypeTableEntryIdUnreachable)
{
- 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) {
- 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) {
- return false;
+ result.id = ConstCastResultIdFnGenericArgCount;
+ return result;
}
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);
@@ -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 *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)) {
- return false;
+ ConstCastOnly arg_child = types_match_const_cast_only(g, actual_param_info->type, expected_param_info->type);
+ 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) {
- return false;
+ result.id = ConstCastResultIdFnArgNoAlias;
+ result.data.arg_no_alias.arg_index = i;
+ return result;
}
}
- return true;
+ return result;
}
-
- return false;
+ result.id = ConstCastResultIdType;
+ return result;
}
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name) {
src/analyze.hpp
@@ -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);
-bool types_match_const_cast_only(CodeGen *g, TypeTableEntry *expected_type, TypeTableEntry *actual_type);
VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, 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);
@@ -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);
+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
src/ir.cpp
@@ -6428,6 +6428,9 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
return ImplicitCastMatchResultYes;
}
+ // if we got here with error sets, make an error showing the incompatibilities
+ if (expected_typek
+
// implicit conversion from anything to var
if (expected_type->id == TypeTableEntryIdVar) {
return ImplicitCastMatchResultYes;
@@ -6801,9 +6804,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
errors[error_entry->value] = error_entry;
}
continue;
- }
- if (prev_type->id == TypeTableEntryIdErrorUnion) {
- // check if the cur type error set must be a subset
+ } else {
+ // check if the cur type error set is a subset
bool prev_is_superset = true;
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];
@@ -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);
switch (result) {
case ImplicitCastMatchResultNo:
- ir_add_error(ira, value,
+ ErrorMsg *msg = ir_add_error(ira, value,
buf_sprintf("expected type '%s', found '%s'",
buf_ptr(&expected_type->name),
buf_ptr(&value->value.type->name)));