@@ -1080,6 +1080,19 @@ pub fn resolveBracketAccessType(analyser: *Analyser, lhs: Type, rhs: BracketAcce
10801080fn bracketAccessTypeFromIPIndex (analyser : * Analyser , ip_index : InternPool.Index ) error {OutOfMemory }! Type {
10811081 std .debug .assert (analyser .ip .typeOf (ip_index ) == .type_type );
10821082 return switch (analyser .ip .indexToKey (ip_index )) {
1083+ .tuple_type = > | info | {
1084+ const types = try info .types .dupe (analyser .gpa , analyser .ip );
1085+ defer analyser .gpa .free (types );
1086+
1087+ const elem_ty_slice = try analyser .arena .alloc (Type , types .len );
1088+ for (elem_ty_slice , types ) | * elem_ty , ty |
1089+ elem_ty .* = try analyser .bracketAccessTypeFromIPIndex (ty );
1090+
1091+ return .{
1092+ .data = .{ .tuple = elem_ty_slice },
1093+ .is_type_val = true ,
1094+ };
1095+ },
10831096 .vector_type = > | info | .{
10841097 .data = .{
10851098 .array = .{
@@ -1307,7 +1320,20 @@ pub fn resolvePropertyType(analyser: *Analyser, ty: Type, name: []const u8) erro
13071320 }
13081321 },
13091322
1310- // TODO: tuple_type
1323+ .tuple_type = > | tuple_info | {
1324+ if (std .mem .eql (u8 , "len" , name )) {
1325+ const index = try analyser .ip .get (.{
1326+ .int_u64_value = .{
1327+ .ty = .usize_type ,
1328+ .int = tuple_info .types .len ,
1329+ },
1330+ });
1331+ return Type .fromIP (analyser , .usize_type , index );
1332+ }
1333+ if (! allDigits (name )) return null ;
1334+ const index = std .fmt .parseInt (u16 , name , 10 ) catch return null ;
1335+ return try analyser .resolveBracketAccessType (ty , .{ .single = index });
1336+ },
13111337
13121338 .optional_type = > | optional_info | {
13131339 if (std .mem .eql (u8 , "?" , name )) {
@@ -1962,10 +1988,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
19621988 if (param .type .data == .anytype_parameter ) return .unknown_type ;
19631989 elem_ty .* = param .type ;
19641990 }
1965- return .{
1966- .data = .{ .tuple = elem_ty_slice },
1967- .is_type_val = true ,
1968- };
1991+ return try Type .createTupleType (analyser , elem_ty_slice );
19691992 }
19701993
19711994 if (std .mem .eql (u8 , func_name , "Tag" )) {
@@ -2117,10 +2140,8 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
21172140 elem_ty .* = try analyser .resolveTypeOfNodeInternal (.of (element , handle )) orelse return null ;
21182141 elem_ty .* = try elem_ty .typeOf (analyser );
21192142 }
2120- return .{
2121- .data = .{ .tuple = elem_ty_slice },
2122- .is_type_val = false ,
2123- };
2143+ const tuple_ty = try Type .createTupleType (analyser , elem_ty_slice );
2144+ return try tuple_ty .instanceUnchecked (analyser );
21242145 },
21252146 .error_union = > {
21262147 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
@@ -2201,10 +2222,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
22012222 }
22022223
22032224 if (has_unresolved_fields ) return null ;
2204- return .{
2205- .data = .{ .tuple = elem_ty_slice },
2206- .is_type_val = true ,
2207- };
2225+ return try Type .createTupleType (analyser , elem_ty_slice );
22082226 }
22092227
22102228 return try analyser .innermostContainer (handle , tree .tokenStart (tree .firstToken (node )));
@@ -3268,6 +3286,26 @@ pub const Type = struct {
32683286 };
32693287 }
32703288
3289+ fn createTuple (analyser : * Analyser , elem_tys : []Type ) ! Data {
3290+ const tys = try analyser .gpa .alloc (InternPool .Index , elem_tys .len );
3291+ defer analyser .gpa .free (tys );
3292+
3293+ const vals = try analyser .gpa .alloc (InternPool .Index , elem_tys .len );
3294+ defer analyser .gpa .free (vals );
3295+
3296+ for (tys , vals , elem_tys ) | * ty , * val , elem_ty | {
3297+ ty .* = elem_ty .ipIndex () orelse break ;
3298+ val .* = .none ;
3299+ } else {
3300+ const types = try analyser .ip .getIndexSlice (tys );
3301+ const values = try analyser .ip .getIndexSlice (vals );
3302+ const index = try analyser .ip .get (.{ .tuple_type = .{ .types = types , .values = values } });
3303+ return .{ .ip_index = .{ .type = .type_type , .index = index } };
3304+ }
3305+
3306+ return .{ .tuple = elem_tys };
3307+ }
3308+
32713309 fn createOptional (analyser : * Analyser , child_ty : Type ) ! Data {
32723310 std .debug .assert (child_ty .is_type_val );
32733311 if (child_ty .ipIndex ()) | payload_type | {
@@ -3581,14 +3619,15 @@ pub const Type = struct {
35813619 const elem_ty = try analyser .resolveGenericTypeInternal (info .elem_ty .* , bound_params , visiting );
35823620 return try createArray (analyser , elem_count , sentinel , elem_ty );
35833621 },
3584- .tuple = > | info | return . {
3585- . tuple = blk : {
3622+ .tuple = > | info | {
3623+ const elem_tys = blk : {
35863624 const types = try analyser .arena .alloc (Type , info .len );
35873625 for (info , types ) | old , * new | {
35883626 new .* = try analyser .resolveGenericTypeInternal (old , bound_params , visiting );
35893627 }
35903628 break :blk types ;
3591- },
3629+ };
3630+ return try createTuple (analyser , elem_tys );
35923631 },
35933632 .optional = > | info | {
35943633 const child_ty = try analyser .resolveGenericTypeInternal (info .* , bound_params , visiting );
@@ -3691,6 +3730,13 @@ pub const Type = struct {
36913730 };
36923731 }
36933732
3733+ fn createTupleType (analyser : * Analyser , elem_tys : []Type ) ! Type {
3734+ return .{
3735+ .data = try Data .createTuple (analyser , elem_tys ),
3736+ .is_type_val = true ,
3737+ };
3738+ }
3739+
36943740 fn createOptionalType (analyser : * Analyser , child_ty : Type ) ! Type {
36953741 return .{
36963742 .data = try Data .createOptional (analyser , child_ty ),
@@ -4164,8 +4210,16 @@ pub const Type = struct {
41644210 return self .getContainerKind () == container_kind_tok ;
41654211 }
41664212
4167- pub fn isStructType (self : Type ) bool {
4168- return self .data == .tuple or self .isContainerKind (.keyword_struct ) or self .isRoot ();
4213+ pub fn isStructType (self : Type , analyser : * Analyser ) bool {
4214+ if (! self .is_type_val ) return false ;
4215+ return switch (self .data ) {
4216+ .tuple = > true ,
4217+ .ip_index = > | payload | {
4218+ const index = payload .index orelse return false ;
4219+ return analyser .ip .zigTypeTag (index ) == .@"struct" ;
4220+ },
4221+ else = > self .isContainerKind (.keyword_struct ) or self .isRoot (),
4222+ };
41694223 }
41704224
41714225 pub fn isNamespace (self : Type ) bool {
@@ -5052,7 +5106,7 @@ pub fn getFieldAccessType(
50525106 }
50535107 } else return null ;
50545108 if (current_type ) | ct | {
5055- if (ct .isStructType () or ct .isUnionType ()) {
5109+ if (ct .isStructType (analyser ) or ct .isUnionType ()) {
50565110 // struct initialization
50575111 current_type = try ct .instanceTypeVal (analyser );
50585112 }
@@ -5832,9 +5886,16 @@ pub const DeclWithHandle = struct {
58325886
58335887 const init_node = tree .nodeData (pay .node ).extra_and_node [1 ];
58345888 const node = try analyser .resolveTypeOfNode (.of (init_node , self .handle )) orelse return null ;
5889+ if (node .is_type_val ) return null ;
58355890 break :blk switch (node .data ) {
58365891 .array = > | array_info | try array_info .elem_ty .instanceTypeVal (analyser ),
58375892 .tuple = > try analyser .resolveBracketAccessType (node , .{ .single = pay .index }),
5893+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .type )) {
5894+ .vector_type = > | vector_info | Type .fromIP (analyser , vector_info .child , null ),
5895+ .array_type = > | array_info | Type .fromIP (analyser , array_info .child , null ),
5896+ .tuple_type = > try analyser .resolveBracketAccessType (node , .{ .single = pay .index }),
5897+ else = > null ,
5898+ },
58385899 else = > null ,
58395900 };
58405901 },
0 commit comments