mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Disambiguate types when they have the same name and need cast between each other.
This commit is contained in:
@@ -88,6 +88,7 @@
|
|||||||
- Deprecated `@select` in favor of `???`.
|
- Deprecated `@select` in favor of `???`.
|
||||||
- Enum inference, like `Foo x = $eval("A")`, now works correctly for `$eval`.
|
- Enum inference, like `Foo x = $eval("A")`, now works correctly for `$eval`.
|
||||||
- Fix regression where files were added more than once. #2442
|
- Fix regression where files were added more than once. #2442
|
||||||
|
- Disambiguate types when they have the same name and need cast between each other.
|
||||||
|
|
||||||
### Stdlib changes
|
### Stdlib changes
|
||||||
- Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`.
|
- Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`.
|
||||||
|
|||||||
@@ -2584,6 +2584,9 @@ FunctionPrototype *type_get_resolved_prototype(Type *type);
|
|||||||
bool type_is_inner_type(Type *type);
|
bool type_is_inner_type(Type *type);
|
||||||
const char *type_to_error_string(Type *type);
|
const char *type_to_error_string(Type *type);
|
||||||
const char *type_quoted_error_string(Type *type);
|
const char *type_quoted_error_string(Type *type);
|
||||||
|
const char *type_quoted_error_string_with_path(Type *type);
|
||||||
|
const char *type_error_string_maybe_with_path(Type *type, Type *other_type);
|
||||||
|
const char *type_quoted_error_string_maybe_with_path(Type *type, Type *other_type);
|
||||||
INLINE bool type_may_negate(Type *type);
|
INLINE bool type_may_negate(Type *type);
|
||||||
INLINE bool type_is_builtin(TypeKind kind);
|
INLINE bool type_is_builtin(TypeKind kind);
|
||||||
INLINE bool type_convert_will_trunc(Type *destination, Type *source);
|
INLINE bool type_convert_will_trunc(Type *destination, Type *source);
|
||||||
|
|||||||
@@ -727,21 +727,23 @@ static bool report_cast_error(CastContext *cc, bool may_cast_explicit)
|
|||||||
}
|
}
|
||||||
if (may_cast_explicit)
|
if (may_cast_explicit)
|
||||||
{
|
{
|
||||||
|
Type *typeto = type_no_optional(to);
|
||||||
|
Type *from = type_no_optional(expr->type);
|
||||||
if (expr->type->canonical->type_kind == TYPE_DISTINCT
|
if (expr->type->canonical->type_kind == TYPE_DISTINCT
|
||||||
&& type_no_optional(to)->canonical->type_kind == TYPE_DISTINCT)
|
&& type_no_optional(to)->canonical->type_kind == TYPE_DISTINCT)
|
||||||
{
|
{
|
||||||
RETURN_CAST_ERROR(expr,
|
RETURN_CAST_ERROR(expr,
|
||||||
"Implicitly casting %s to %s is not permitted. It's possible to do an explicit cast by placing '(%s)' before the expression. However, explicit casts between distinct types are usually not intended and are not safe.",
|
"Implicitly casting %s to %s is not permitted. It's possible to do an explicit cast by placing '(%s)' before the expression. However, explicit casts between distinct types are usually not intended and are not safe.",
|
||||||
type_quoted_error_string(type_no_optional(expr->type)),
|
type_quoted_error_string_maybe_with_path(from, typeto),
|
||||||
type_quoted_error_string(to),
|
type_quoted_error_string_maybe_with_path(to, from),
|
||||||
type_to_error_string(type_no_optional(to)));
|
type_error_string_maybe_with_path(typeto, from));
|
||||||
|
|
||||||
}
|
}
|
||||||
RETURN_CAST_ERROR(expr,
|
RETURN_CAST_ERROR(expr,
|
||||||
"Implicitly casting %s to %s is not permitted, but you may do an explicit cast by placing '(%s)' before the expression.",
|
"Implicitly casting %s to %s is not permitted, but you may do an explicit cast by placing '(%s)' before the expression.",
|
||||||
type_quoted_error_string(type_no_optional(expr->type)),
|
type_quoted_error_string_maybe_with_path(from, typeto),
|
||||||
type_quoted_error_string(to),
|
type_quoted_error_string_maybe_with_path(to, from),
|
||||||
type_to_error_string(type_no_optional(to)));
|
type_error_string_maybe_with_path(typeto, from));
|
||||||
}
|
}
|
||||||
if (to->type_kind == TYPE_INTERFACE)
|
if (to->type_kind == TYPE_INTERFACE)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static Type *flatten_raw_function_type(Type *type);
|
static Type *flatten_raw_function_type(Type *type);
|
||||||
|
static const char *type_to_error_string_with_path(Type *type);
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@@ -99,6 +100,18 @@ Type *type_int_unsigned_by_bitsize(BitSize bit_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *type_quoted_error_string_maybe_with_path(Type *type, Type *other_type)
|
||||||
|
{
|
||||||
|
if (!str_eq(type_no_optional(type)->name, type_no_optional(other_type)->name)) return type_quoted_error_string(type);
|
||||||
|
return type_quoted_error_string_with_path(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *type_error_string_maybe_with_path(Type *type, Type *other_type)
|
||||||
|
{
|
||||||
|
if (!str_eq(type_no_optional(type)->name, type_no_optional(other_type)->name)) return type_to_error_string(type);
|
||||||
|
return type_to_error_string_with_path(type);
|
||||||
|
}
|
||||||
|
|
||||||
const char *type_quoted_error_string(Type *type)
|
const char *type_quoted_error_string(Type *type)
|
||||||
{
|
{
|
||||||
if (type->canonical != type)
|
if (type->canonical != type)
|
||||||
@@ -108,6 +121,15 @@ const char *type_quoted_error_string(Type *type)
|
|||||||
return str_printf("'%s'", type_to_error_string(type));
|
return str_printf("'%s'", type_to_error_string(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *type_quoted_error_string_with_path(Type *type)
|
||||||
|
{
|
||||||
|
if (type->canonical != type)
|
||||||
|
{
|
||||||
|
return str_printf("'%s' (%s)", type_to_error_string_with_path(type), type_to_error_string_with_path(type->canonical));
|
||||||
|
}
|
||||||
|
return str_printf("'%s'", type_to_error_string_with_path(type));
|
||||||
|
}
|
||||||
|
|
||||||
void type_append_name_to_scratch(Type *type)
|
void type_append_name_to_scratch(Type *type)
|
||||||
{
|
{
|
||||||
type = type->canonical;
|
type = type->canonical;
|
||||||
@@ -234,6 +256,7 @@ static void type_add_parent_to_scratch(Decl *decl)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *type_to_error_string(Type *type)
|
const char *type_to_error_string(Type *type)
|
||||||
{
|
{
|
||||||
switch (type->type_kind)
|
switch (type->type_kind)
|
||||||
@@ -301,6 +324,77 @@ const char *type_to_error_string(Type *type)
|
|||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *type_to_error_string_with_path(Type *type)
|
||||||
|
{
|
||||||
|
switch (type->type_kind)
|
||||||
|
{
|
||||||
|
case TYPE_POISONED:
|
||||||
|
return "poisoned";
|
||||||
|
case TYPE_VOID:
|
||||||
|
case TYPE_BOOL:
|
||||||
|
case ALL_INTS:
|
||||||
|
case ALL_FLOATS:
|
||||||
|
case TYPE_ANYFAULT:
|
||||||
|
case TYPE_UNTYPED_LIST:
|
||||||
|
case TYPE_ANY:
|
||||||
|
case TYPE_MEMBER:
|
||||||
|
case TYPE_WILDCARD:
|
||||||
|
return type->name;
|
||||||
|
case TYPE_ENUM:
|
||||||
|
case TYPE_CONST_ENUM:
|
||||||
|
case TYPE_TYPEDEF:
|
||||||
|
case TYPE_STRUCT:
|
||||||
|
case TYPE_UNION:
|
||||||
|
case TYPE_DISTINCT:
|
||||||
|
case TYPE_BITSTRUCT:
|
||||||
|
case TYPE_INTERFACE:
|
||||||
|
{
|
||||||
|
Decl *decl = type->decl;
|
||||||
|
const char *suffix = decl->unit->module->generic_suffix;
|
||||||
|
scratch_buffer_clear();
|
||||||
|
scratch_buffer_append(decl->unit->module->name->module);
|
||||||
|
scratch_buffer_append("::");
|
||||||
|
if (suffix || type_is_inner_type(type))
|
||||||
|
{
|
||||||
|
type_add_parent_to_scratch(decl);
|
||||||
|
}
|
||||||
|
scratch_buffer_append(decl->name);
|
||||||
|
if (suffix) scratch_buffer_append(suffix);
|
||||||
|
return scratch_buffer_copy();
|
||||||
|
}
|
||||||
|
case TYPE_FUNC_PTR:
|
||||||
|
type = type->pointer;
|
||||||
|
FALLTHROUGH;
|
||||||
|
case TYPE_FUNC_RAW:
|
||||||
|
if (!type->function.prototype) return type->name;
|
||||||
|
scratch_buffer_clear();
|
||||||
|
scratch_buffer_append("fn ");
|
||||||
|
type_append_func_to_scratch(type->function.prototype);
|
||||||
|
return scratch_buffer_copy();
|
||||||
|
case TYPE_INFERRED_VECTOR:
|
||||||
|
return str_printf("%s[<*>]", type_to_error_string_with_path(type->array.base));
|
||||||
|
case TYPE_VECTOR:
|
||||||
|
return str_printf("%s[<%llu>]", type_to_error_string_with_path(type->array.base), (unsigned long long)type->array.len);
|
||||||
|
case TYPE_TYPEINFO:
|
||||||
|
return "typeinfo";
|
||||||
|
case TYPE_TYPEID:
|
||||||
|
return "typeid";
|
||||||
|
case TYPE_POINTER:
|
||||||
|
return str_printf("%s*", type_to_error_string_with_path(type->pointer));
|
||||||
|
case TYPE_OPTIONAL:
|
||||||
|
if (!type->optional) return "void?";
|
||||||
|
return str_printf("%s?", type_to_error_string_with_path(type->optional));
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
return str_printf("%s[%llu]", type_to_error_string_with_path(type->array.base), (unsigned long long)type->array.len);
|
||||||
|
case TYPE_INFERRED_ARRAY:
|
||||||
|
case TYPE_FLEXIBLE_ARRAY:
|
||||||
|
return str_printf("%s[*]", type_to_error_string_with_path(type->array.base));
|
||||||
|
case TYPE_SLICE:
|
||||||
|
return str_printf("%s[]", type_to_error_string_with_path(type->array.base));
|
||||||
|
}
|
||||||
|
UNREACHABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool type_is_matching_int(CanonicalType *type1, CanonicalType *type2)
|
bool type_is_matching_int(CanonicalType *type1, CanonicalType *type2)
|
||||||
{
|
{
|
||||||
|
|||||||
15
test/test_suite/cast/implicit_cast_same_name.c3
Normal file
15
test/test_suite/cast/implicit_cast_same_name.c3
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
module foo::a;
|
||||||
|
struct Lexer { int a; }
|
||||||
|
fn void foo(Lexer *lex) {}
|
||||||
|
|
||||||
|
module foo::b;
|
||||||
|
struct Lexer { int a; }
|
||||||
|
fn void foo(Lexer *lex) {}
|
||||||
|
|
||||||
|
module foo;
|
||||||
|
|
||||||
|
fn void bar()
|
||||||
|
{
|
||||||
|
a::Lexer l;
|
||||||
|
b::foo(&l); // #error: Implicitly casting 'foo::a::Lexer*' to 'foo::b::Lexer*' is not permitted, but you may do an explicit cast by placing '(foo::b::Lexer*)' before the expression
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user