diff --git a/lib/std/net/socket.c3 b/lib/std/net/socket.c3 index eda3569ad..dc35b5583 100644 --- a/lib/std/net/socket.c3 +++ b/lib/std/net/socket.c3 @@ -72,9 +72,7 @@ fn ulong! poll(Poll[] polls, Duration timeout) $else CInt result = os::poll((Posix_pollfd*)polls.ptr, (Posix_nfds_t)polls.len, (CInt)time_ms); $endif - if (result == 0) return 0; - if (result > 0) return (ulong)result; - return os::socket_error()?; + return result < 0 ? os::socket_error()? : (ulong)result; } macro Socket new_socket(fd, ai) diff --git a/resources/examples/notworking/globals.c3 b/resources/examples/notworking/globals.c3 deleted file mode 100644 index e0f35f721..000000000 --- a/resources/examples/notworking/globals.c3 +++ /dev/null @@ -1,35 +0,0 @@ -module globals; - - -const String CLICK_ME = "Click Me"; -uint counter = 0; - -fn void clickedme(GtkButton *o, void *d) -{ - (GtkLabel*)(d).set_text(string.format("You clicked me %d times", ++counter)); -} - -fn void main(String[] argv) -{ - gtk::init(&argc, &argv); - - GtkWindow *win = gtk::windowCreate(GtkWindow.TOPLEVEL); - win.set_title(CLICK_ME); - - GtkButton *button = gtk::buttonCreateWithLabel(CLICK_ME); - - GtkLabel *label = GtkLabel.new("There have been no clicks yet"); - label.setSingleLineMode(true); - - GtkVBox vbox = gtk::vBoxCreate(true, 1); - vbox.add(label); - vbox.add(button); - - win.add(vbox); - - win.connectSignal("delete-event", gtk::mainQuit, NULL); - button.connectSignal("clicked", &clickedme, label); - - win.showAll(); - gtk::main(); -} diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index f9219a18d..4522adf62 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2100,7 +2100,6 @@ bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type); bool may_cast(SemaContext *cc, Expr *expr, Type *to_type, bool is_explicit); void cast_no_check(Expr *expr, Type *to_type, bool add_optional); -Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type); bool cast_to_index(SemaContext *context, Expr *index); CastKind cast_to_bool_kind(Type *type); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index f42c69bc9..44fb298a7 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -255,13 +255,12 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type) case TYPE_INFERRED_VECTOR: assert(type_is_arraylike(type_flatten(actual_type))); return type_add_optional(type_get_vector(indexed, type_flatten(actual_type)->array.len), is_optional); + case TYPE_SUBARRAY: + return type_add_optional(type_get_subarray(indexed), is_optional); case TYPE_VECTOR: // This is unreachable, because unlike arrays, there is no inner type that may be // the inferred part. UNREACHABLE - case TYPE_SUBARRAY: - // The case of int[*][] y = ... is disallowed - UNREACHABLE default: UNREACHABLE } @@ -761,7 +760,7 @@ static bool rule_int_to_ptr(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_ptr_to_int(CastContext *cc, bool is_explicit, bool is_silent) { - bool too_small = type_size(cc->to_type) < type_size(type_uptr); + bool too_small = type_size(cc->to) < type_size(type_uptr); if (!is_explicit) return sema_cast_error(cc, !too_small, is_silent); // The type must be uptr or bigger. @@ -883,7 +882,7 @@ static bool rule_arr_to_arr(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_arr_to_vec(CastContext *cc, bool is_explicit, bool is_silent) { ArraySize len = cc->from_type->array.len; - if (len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent); + if (len != cc->to->array.len) return sema_cast_error(cc, false, is_silent); Type *base = cc->from_type->array.base; switch (type_to_group(type_flatten(base))) { @@ -908,7 +907,7 @@ static bool rule_arr_to_vec(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_vec_to_arr(CastContext *cc, bool is_explicit, bool is_silent) { ArraySize len = cc->from_type->array.len; - if (len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent); + if (len != cc->to->array.len) return sema_cast_error(cc, false, is_silent); Type *base = cc->from_type->array.base; cast_context_set_from(cc, type_get_array(base, len)); return cast_is_allowed(cc, is_explicit, is_silent); @@ -946,6 +945,14 @@ static bool rule_sa_to_vecarr(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_sa_to_infer(CastContext *cc, bool is_explicit, bool is_silent) { Expr *expr = cc->expr; + // 1. We might infer something above. + if (cc->to->type_kind == TYPE_SUBARRAY) + { + cast_context_set_from(cc, cc->from_type->array.base); + cast_context_set_to(cc, cc->to->array.base); + return cast_is_allowed(cc, is_explicit, is_silent); + } + // 2. Otherwise there is a vector matching. MemberIndex size = sema_len_from_const(expr); if (size < 0) { @@ -963,16 +970,16 @@ static bool rule_sa_to_infer(CastContext *cc, bool is_explicit, bool is_silent) static bool rule_vecarr_to_infer(CastContext *cc, bool is_explicit, bool is_silent) { - Type *new_type = type_infer_len_from_actual_type(cc->from_type, cc->to_type); + Type *new_type = type_infer_len_from_actual_type(cc->to, cc->from_type); cast_context_set_to(cc, new_type); return cast_is_allowed(cc, is_explicit, is_silent); } static bool rule_ptr_to_infer(CastContext *cc, bool is_explicit, bool is_silent) { - if (cc->to_type->type_kind != TYPE_POINTER) return sema_cast_error(cc, false, is_silent); + if (cc->to->type_kind != TYPE_POINTER) return sema_cast_error(cc, false, is_silent); - Type *new_type = type_infer_len_from_actual_type(cc->from_type, cc->to_type); + Type *new_type = type_infer_len_from_actual_type(cc->to, cc->from_type); cast_context_set_to(cc, new_type->pointer->canonical); cast_context_set_from(cc, cc->from_type->pointer); return cast_is_allowed(cc, is_explicit, is_silent); @@ -1108,7 +1115,7 @@ static bool rule_struct_to_struct(CastContext *cc, bool is_explicit, bool is_sil static bool rule_vec_to_vec(CastContext *cc, bool is_explicit, bool is_silent) { - if (cc->from_type->array.len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent); + if (cc->from_type->array.len != cc->to->array.len) return sema_cast_error(cc, false, is_silent); Type *from_base = cc->from_type->array.base; cast_context_set_to(cc, cc->to->array.base); // Allow bool vectors to expand to any int. @@ -1167,8 +1174,8 @@ static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent) { if (is_silent && !is_explicit) return false; Type *base_type = cc->from_type->decl->bitstruct.base_type->type->canonical; - Type *to_type = cc->to_type; - if (base_type != to_type) return sema_cast_error(cc, false, is_silent); + Type *to = cc->to; + if (base_type != to) return sema_cast_error(cc, false, is_silent); if (!is_explicit) return sema_cast_error(cc, true, is_silent); return true; } @@ -1177,10 +1184,10 @@ static bool rule_bits_to_int(CastContext *cc, bool is_explicit, bool is_silent) { if (is_silent && !is_explicit) return false; Type *base_type = cc->from_type->decl->bitstruct.base_type->type->canonical; - Type *to_type = cc->to_type; - if (base_type != to_type) + Type *to = cc->to; + if (base_type != to) { - if (!type_is_integer(base_type) || type_size(to_type) != type_size(base_type)) + if (!type_is_integer(base_type) || type_size(to) != type_size(base_type)) { return sema_cast_error(cc, false, is_silent); } @@ -1729,6 +1736,14 @@ static void cast_sa_to_sa(Expr *expr, Type *to_type) static void cast_sa_to_vecarr(Expr *expr, Type *to_type) { + if (!expr_is_const(expr)) + { + assert(expr->expr_kind == EXPR_CAST); + Expr *inner = exprptr(expr->cast_expr.expr)->unary_expr.expr; + expr_replace(expr, inner); + cast_no_check(expr, to_type, false); + return; + } assert(expr_is_const(expr)); expr->type = to_type; return; @@ -1736,18 +1751,11 @@ static void cast_sa_to_vecarr(Expr *expr, Type *to_type) static void cast_sa_to_infer(Expr *expr, Type *to_type) { - assert(expr_is_const(expr)); - Type *index = type_get_indexed_type(to_type); - MemberIndex size = sema_len_from_const(expr); - assert(size > 0); - if (type_flatten(to_type)->type_kind == TYPE_VECTOR) - { - expr->type = type_get_vector(index, size); - } - else - { - expr->type = type_get_array(index, size); - } + ArraySize len = sema_len_from_const(expr); + assert(len > 0); + Type *indexed = type_get_indexed_type(expr->type); + to_type = type_infer_len_from_actual_type(to_type, type_get_array(indexed, len)); + cast_no_check(expr, to_type, false); } static void cast_vecarr_to_infer(Expr *expr, Type *to_type) diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 264629aab..78ffc0da1 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3046,12 +3046,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) if (infer_len) { - if (type_is_inferred(init->type)) - { - SEMA_ERROR(decl->var.type_info, "You cannot use [*] and [<*>] underlying types with initializers."); - return decl_poison(decl); - } - decl->type = type_infer_len_from_actual_type(decl->type, init->type); + decl->type = type_add_optional(init->type, IS_OPTIONAL(decl)); } Expr *init_expr = decl->var.init_expr; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index fda73470d..cc585417e 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -8109,10 +8109,21 @@ static MemberIndex len_from_const_initializer(ConstInitializer *init) } UNREACHABLE } -MemberIndex sema_len_from_const(Expr *expr_maybe_const) +MemberIndex sema_len_from_const(Expr *expr) { - if (!expr_is_const(expr_maybe_const)) return -1; - switch (expr_maybe_const->const_expr.const_kind) + // We also handle the case where we have a cast from a const array. + if (!expr_is_const(expr)) + { + if (expr->type->type_kind != TYPE_SUBARRAY) return -1; + if (expr->expr_kind != EXPR_CAST) return -1; + if (expr->cast_expr.kind != CAST_APTSA) return -1; + Expr *inner = exprptr(expr->cast_expr.expr); + if (inner->expr_kind != EXPR_UNARY || inner->unary_expr.operator != UNARYOP_ADDR) return -1; + inner = inner->unary_expr.expr; + if (!expr_is_const(inner)) return -1; + expr = inner; + } + switch (expr->const_expr.const_kind) { case CONST_FLOAT: case CONST_INTEGER: @@ -8125,11 +8136,11 @@ MemberIndex sema_len_from_const(Expr *expr_maybe_const) return -1; case CONST_BYTES: case CONST_STRING: - return expr_maybe_const->const_expr.bytes.len; + return expr->const_expr.bytes.len; case CONST_INITIALIZER: - return len_from_const_initializer(expr_maybe_const->const_expr.initializer); + return len_from_const_initializer(expr->const_expr.initializer); case CONST_UNTYPED_LIST: - return vec_size(expr_maybe_const->const_expr.untyped_list); + return vec_size(expr->const_expr.untyped_list); } UNREACHABLE } diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index 743496760..fac8345f2 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -308,7 +308,6 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex if (!sema_analyse_expr_rhs(context, inner_type, element, true)) return false; if (inner_is_inferred) { - Type *element_type = type_no_optional(element->type); if (inferred_element) { if (!cast_implicit(context, element, inferred_element)) @@ -319,7 +318,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex } else { - inferred_element = type_infer_len_from_actual_type(inner_type, element_type); + inferred_element = element->type; } } } diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index b92e6c3ac..421ac1085 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -81,7 +81,7 @@ int sema_check_comp_time_bool(SemaContext *context, Expr *expr); bool sema_expr_check_assign(SemaContext *c, Expr *expr); bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, CallABI abi, Signature *signature, bool is_real_function); bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type); -MemberIndex sema_len_from_const(Expr *expr_maybe_const); +MemberIndex sema_len_from_const(Expr *expr); void cast_promote_vararg(Expr *arg); Type *cast_numeric_arithmetic_promotion(Type *type); diff --git a/test/test_suite/arrays/inferred_subarray.c3 b/test/test_suite/arrays/inferred_subarray.c3 new file mode 100644 index 000000000..b2b667643 --- /dev/null +++ b/test/test_suite/arrays/inferred_subarray.c3 @@ -0,0 +1,5 @@ +fn void main() +{ + int[*][*][] x = int[2][1][] { { { 1, 2 } } }; + int[*][*][*] y = int[2][1][] { { { 1, 2 } } }; +}