@@ -542,31 +542,78 @@ fn minify_sort_fn(a &ast.StructField, b &ast.StructField) int {
542542 }
543543}
544544
545- fn (mut c Checker) struct_init_selector_type_expr (expr ast.SelectorExpr) ast.Type {
546- if expr.expr is ast.TypeOf {
547- return c.type_resolver.typeof_field_type (c.type_resolver.typeof_type (expr.expr.expr,
548- expr.name_type), expr.field_name)
545+ fn (mut c Checker) struct_init_selector_type_expr (mut expr ast.SelectorExpr) ast.Type {
546+ if ! is_array_init_type_expr_field (expr.field_name) {
547+ return ast.void_type
548+ }
549+ base_type := c.struct_init_type_expr (mut expr.expr)
550+ if base_type == ast.void_type {
551+ return ast.void_type
549552 }
550- return ast.void_type
553+ return c.type_resolver. typeof_field_type (base_type, expr.field_name)
551554}
552555
553- fn (mut c Checker) struct_init_type_expr (expr ast.Expr) ast.Type {
554- return match expr {
556+ fn (mut c Checker) struct_init_type_expr (mut expr ast.Expr) ast.Type {
557+ return match mut expr {
555558 ast.TypeNode {
556559 expr.typ
557560 }
558561 ast.ParExpr {
559- c.struct_init_type_expr (expr.expr)
562+ c.struct_init_type_expr (mut expr.expr)
563+ }
564+ ast.TypeOf {
565+ if expr.is_type {
566+ c.recheck_concrete_type (expr.typ)
567+ } else {
568+ if expr.typ == 0 || expr.typ == ast.void_type || expr.typ == ast.no_type {
569+ expr.typ = c.expr (mut expr.expr)
570+ }
571+ resolved_type := c.recheck_concrete_type (expr.typ)
572+ if resolved_type != 0 && resolved_type != ast.void_type
573+ && resolved_type != ast.no_type {
574+ resolved_type
575+ } else {
576+ c.recheck_concrete_type (c.type_resolver.typeof_type (expr.expr, expr.typ))
577+ }
578+ }
579+ }
580+ ast.Ident {
581+ if c.is_generic_type_expr_ident (expr.name) {
582+ c.table.find_type (expr.name).set_flag (.generic)
583+ } else {
584+ c.get_expr_type (expr)
585+ }
560586 }
561587 ast.SelectorExpr {
562- c.struct_init_selector_type_expr (expr)
588+ c.struct_init_selector_type_expr (mut expr)
563589 }
564590 else {
565591 ast.void_type
566592 }
567593 }
568594}
569595
596+ fn (c &Checker) struct_init_uses_comptime_type_accessor (expr ast.Expr) bool {
597+ return match expr {
598+ ast.ParExpr {
599+ c.struct_init_uses_comptime_type_accessor (expr.expr)
600+ }
601+ ast.SelectorExpr {
602+ mut is_base_type_expr := expr.expr is ast.TypeOf
603+ || c.struct_init_uses_comptime_type_accessor (expr.expr)
604+ if expr.expr is ast.Ident {
605+ is_base_type_expr = is_base_type_expr
606+ || c.is_generic_type_expr_ident (expr.expr.name)
607+ }
608+ expr.field_name in ['idx' , 'typ' , 'unaliased_typ' , 'key_type' , 'value_type' , 'element_type' , 'pointee_type' , 'payload_type' ]
609+ && is_base_type_expr
610+ }
611+ else {
612+ false
613+ }
614+ }
615+ }
616+
570617fn (mut c Checker) struct_init (mut node ast.StructInit, is_field_zero_struct_init bool , mut inited_fields []string ) ast.Type {
571618 util.timing_start (@METHOD)
572619 old_expected_type := c.expected_type
@@ -579,14 +626,20 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
579626 && c.expected_type != ast.void_type && c.expected_type.has_flag (.generic)
580627 && short_syntax_expected_type_sym.kind == .any
581628 && ! short_syntax_expected_type_sym.is_builtin ()
582- if node.typ == ast.void_type && ! node.is_short_syntax && node.typ_expr ! is ast.EmptyExpr {
583- c.expr (mut node.typ_expr)
584- node.typ = c.struct_init_type_expr (node.typ_expr)
585- if node.typ == ast.void_type {
629+ is_comptime_type_struct_init := ! node.is_short_syntax && node.typ_expr ! is ast.EmptyExpr
630+ && c.struct_init_uses_comptime_type_accessor (node.typ_expr)
631+ should_resolve_typ_expr := node.typ == ast.void_type
632+ || (is_comptime_type_struct_init && c.has_active_generic_recheck_context ())
633+ if should_resolve_typ_expr && ! node.is_short_syntax && node.typ_expr ! is ast.EmptyExpr {
634+ if ! is_comptime_type_struct_init {
635+ c.expr (mut node.typ_expr)
636+ }
637+ node.typ = c.struct_init_type_expr (mut node.typ_expr)
638+ if node.typ == ast.void_type || node.typ == ast.no_type {
586639 c.error ('cannot use `${node.typ_expr} ` as a struct init type' , node.typ_expr.pos ())
587640 return ast.void_type
588641 }
589- node.unresolved = node.typ.has_flag (.generic)
642+ node.unresolved = ! is_comptime_type_struct_init && node.typ.has_flag (.generic)
590643 }
591644 source_typ := if node.is_short_syntax && c.expected_type != ast.void_type
592645 && ! short_syntax_infers_anon_from_generic_param {
@@ -769,6 +822,8 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
769822 type_sym := c.table.sym (concrete_node_typ)
770823 is_generic_zero_struct_init := original_node_typ.has_flag (.generic) && node.init_fields.len == 0
771824 && ! node.has_update_expr
825+ is_comptime_type_zero_struct_init := node.init_fields.len == 0 && ! node.has_update_expr
826+ && is_comptime_type_struct_init
772827 if is_generic_zero_struct_init {
773828 // Don't early-return for single-letter types (like F{}) in non-generic functions —
774829 // these are unknown structs that should be caught by ensure_type_exists below.
@@ -778,7 +833,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
778833 return concrete_node_typ
779834 }
780835 }
781- if ! is_field_zero_struct_init {
836+ if ! is_field_zero_struct_init && ! is_comptime_type_zero_struct_init {
782837 type_exists := c.ensure_type_exists (node.typ, node.pos)
783838 if ! type_exists && node.typ.idx () > 0 && c.table.sym (node.typ).kind == .placeholder {
784839 return ast.void_type
@@ -830,7 +885,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
830885 if ! node.has_update_expr && ! type_sym.is_pub && type_sym.kind != .placeholder
831886 && type_sym.language != .c
832887 && (type_sym.mod != c.mod && ! (is_generic_init && type_sym.mod != 'builtin' ))
833- && ! is_field_zero_struct_init {
888+ && ! is_field_zero_struct_init && ! is_comptime_type_zero_struct_init {
834889 c.error ('type `${type_sym.name} ` is private' , node.pos)
835890 }
836891 if type_sym.info is ast.Struct && type_sym.mod != c.mod && ! is_field_zero_struct_init {
0 commit comments