mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Incorrect type checking when &[] and [] return optional values.
- Failed to find subscript overloading on optional values. - Added `&[]` overload to HashMap.
This commit is contained in:
@@ -182,6 +182,24 @@ fn Value*? HashMap.get_ref(&map, Key key)
|
||||
return NOT_FOUND?;
|
||||
}
|
||||
|
||||
fn Value* HashMap.get_or_create_ref(&map, Key key) @operator(&[])
|
||||
{
|
||||
uint hash = rehash(key.hash());
|
||||
if (map.count)
|
||||
{
|
||||
for (Entry *e = map.table[index_for(hash, map.table.len)]; e != null; e = e.next)
|
||||
{
|
||||
if (e.hash == hash && equals(key, e.key)) return &e.value;
|
||||
}
|
||||
}
|
||||
map.set(key, {});
|
||||
for (Entry *e = map.table[index_for(hash, map.table.len)]; e != null; e = e.next)
|
||||
{
|
||||
if (e.hash == hash && equals(key, e.key)) return &e.value;
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
|
||||
fn Entry*? HashMap.get_entry(&map, Key key)
|
||||
{
|
||||
if (!map.count) return NOT_FOUND?;
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
- Compiler assert when calling unassigned CT functions #2418.
|
||||
- Fixed crash in header generation when exporting functions with const enums (#2384).
|
||||
- Fix incorrect panic message when slicing with negative size.
|
||||
- Incorrect type checking when &[] and [] return optional values.
|
||||
- Failed to find subscript overloading on optional values.
|
||||
|
||||
### Stdlib changes
|
||||
- Add `==` to `Pair`, `Triple` and TzDateTime. Add print to `Pair` and `Triple`.
|
||||
@@ -65,6 +67,7 @@
|
||||
- Add Freestanding OS types to runtime `env::` booleans.
|
||||
- Added libloaderapi to `std::os::win32`.
|
||||
- Added `HashSet.values` and `String.contains_char` #2386
|
||||
- Added `&[]` overload to HashMap.
|
||||
|
||||
## 0.7.4 Change list
|
||||
|
||||
|
||||
@@ -1851,7 +1851,7 @@ static bool sema_analyse_operator_common(SemaContext *context, Decl *method, Typ
|
||||
|
||||
Decl *sema_find_untyped_operator(Type *type, OperatorOverload operator_overload, Decl *skipped)
|
||||
{
|
||||
type = type->canonical;
|
||||
type = type_no_optional(type)->canonical;
|
||||
assert(operator_overload < OVERLOAD_TYPED_START);
|
||||
if (!type_may_have_sub_elements(type)) return NULL;
|
||||
Decl *def = type->decl;
|
||||
@@ -2098,7 +2098,7 @@ static inline bool sema_analyse_operator_element_at(SemaContext *context, Decl *
|
||||
RETURN_SEMA_ERROR(rtype, "%s has unknown size and cannot be used as a return type.",
|
||||
type_quoted_error_string(rtype->type));
|
||||
}
|
||||
if (method->func_decl.operator == OVERLOAD_ELEMENT_REF && !type_is_pointer(rtype->type))
|
||||
if (method->func_decl.operator == OVERLOAD_ELEMENT_REF && !type_is_pointer(type_no_optional(rtype->type)))
|
||||
{
|
||||
RETURN_SEMA_ERROR(rtype, "The return type must be a pointer, but it is returning %s, did you mean to overload [] instead?",
|
||||
type_quoted_error_string(rtype->type));
|
||||
@@ -2224,7 +2224,7 @@ static inline void sema_get_overload_arguments(Decl *method, Type **value_ref, T
|
||||
*index_ref = method->func_decl.signature.params[1]->type->canonical;
|
||||
return;
|
||||
case OVERLOAD_ELEMENT_REF:
|
||||
*value_ref = type_no_optional(typeget(method->func_decl.signature.rtype)->canonical->pointer);
|
||||
*value_ref = type_no_optional(typeget(method->func_decl.signature.rtype))->canonical->pointer;
|
||||
*index_ref = method->func_decl.signature.params[1]->type->canonical;
|
||||
return;
|
||||
case OVERLOAD_ELEMENT_SET:
|
||||
|
||||
@@ -11781,7 +11781,7 @@ bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *meth
|
||||
.call_expr.is_func_ref = true,
|
||||
.call_expr.is_type_method = true,
|
||||
};
|
||||
Type *type = parent->type->canonical;
|
||||
Type *type = type_no_optional(parent->type)->canonical;
|
||||
Decl *first_param = method_decl->func_decl.signature.params[0];
|
||||
Type *first = first_param->type->canonical;
|
||||
// Deref / addr as needed.
|
||||
@@ -11796,7 +11796,7 @@ bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *meth
|
||||
if (!sema_expr_rewrite_insert_deref(context, parent)) return false;
|
||||
}
|
||||
}
|
||||
ASSERT_SPAN(method_call, parent && parent->type && first == parent->type->canonical);
|
||||
ASSERT_SPAN(method_call, first == type_no_optional(parent->type)->canonical);
|
||||
unit_register_external_symbol(context, method_decl);
|
||||
if (!sema_expr_analyse_general_call(context, method_call, method_decl, parent, false,
|
||||
NULL)) return expr_poison(method_call);
|
||||
|
||||
@@ -103,3 +103,16 @@ fn void map_copy()
|
||||
assert(hash_map_copy.len() == hash_map.len());
|
||||
|
||||
}
|
||||
|
||||
alias Test = HashMap{String, HashMap {String, String}};
|
||||
fn void test_ref()
|
||||
{
|
||||
Test t;
|
||||
t.init(tmem);
|
||||
(&t["a"]).init(tmem);
|
||||
|
||||
(*&t["a"])["b"] = "ab";
|
||||
test::eq("ab", t["a"]["b"]!!);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user