commit 51c60d8d1a797d936b5d87f2cf4485da989c082f
parent 432d7ce213f2a69447520483adf6c9190a3021d3
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 25 Feb 2021 19:55:21 -0500
check: overhaul alloc type hinting support
Not entirely sure if this is right, but all the tests pass now so
Diffstat:
M | src/check.c | | | 40 | +++++++++++++++++++++++++++++----------- |
1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -195,20 +195,38 @@ check_expr_alloc(struct context *ctx,
inittype = hint;
}
check_expression(ctx, aexpr->alloc.expr, expr->alloc.expr, inittype);
+ inittype = expr->alloc.expr->result;
- enum type_storage storage =
- type_dealias(expr->alloc.expr->result)->storage;
- if (!hint && storage == STORAGE_SLICE) {
- hint = expr->alloc.expr->result;
- } else if (hint) {
- storage = type_dealias(hint)->storage;
- } else {
- hint = type_store_lookup_pointer(ctx->store,
- expr->alloc.expr->result, 0);
+ int flags = 0;
+ if (hint && type_is_assignable(hint, inittype)) {
+ if (type_dealias(hint)->storage == STORAGE_SLICE) {
+ inittype = hint;
+ } else if (type_dealias(hint)->storage == STORAGE_POINTER) {
+ inittype = type_dealias(hint)->pointer.referent;
+ flags = hint->pointer.flags;
+ }
+ }
+
+ switch (type_dealias(inittype)->storage) {
+ case STORAGE_SLICE:
+ expr->result = inittype;
+ break;
+ case STORAGE_ARRAY:
+ if (aexpr->alloc.cap) {
+ expr->result = type_store_lookup_slice(ctx->store,
+ type_dealias(inittype)->array.members);
+ } else {
+ expr->result = type_store_lookup_pointer(ctx->store,
+ inittype, flags);
+ }
+ break;
+ default:
+ expr->result = type_store_lookup_pointer(ctx->store,
+ inittype, flags);
+ break;
}
- expr->result = hint;
- storage = type_dealias(hint)->storage;
+ enum type_storage storage = type_dealias(expr->result)->storage;
switch (storage) {
case STORAGE_POINTER:
if (aexpr->alloc.cap != NULL) {