@@ -1464,6 +1464,148 @@ fn resolveIntegerLiteral(analyser: *Analyser, comptime T: type, options: Resolve
14641464 return analyser .ip .toInt (ip_index , T );
14651465}
14661466
1467+ const IntInfo = union (enum ) {
1468+ comptime_int ,
1469+ fixed_int : std.builtin.Type.Int ,
1470+ };
1471+
1472+ fn intInfo (analyser : * Analyser , ty : InternPool.Index ) ? IntInfo {
1473+ const type_tag = analyser .ip .zigTypeTag (ty ) orelse return null ;
1474+ return switch (type_tag ) {
1475+ .comptime_int = > .comptime_int ,
1476+ .int = > .{ .fixed_int = analyser .ip .intInfo (ty , builtin .target ) },
1477+ else = > null ,
1478+ };
1479+ }
1480+
1481+ fn resolveUnaryIntegerExpression (
1482+ analyser : * Analyser ,
1483+ tag : std.zig.Ast.Node.Tag ,
1484+ instance : Type ,
1485+ ) ! ? Type {
1486+ const index = instance .ipIndex () orelse return null ;
1487+ const ty = analyser .ip .typeOf (index );
1488+ const int_info = analyser .intInfo (ty ) orelse return null ;
1489+ var result = try analyser .ip .toBigInt (analyser .gpa , index ) orelse return null ;
1490+ defer result .deinit ();
1491+ switch (tag ) {
1492+ .bit_not = > switch (int_info ) {
1493+ .comptime_int = > return null ,
1494+ .fixed_int = > | info | _ = try result .bitNotWrap (& result , info .signedness , info .bits ),
1495+ },
1496+ .negation = > result .negate (),
1497+ .negation_wrap = > switch (int_info ) {
1498+ .comptime_int = > result .negate (),
1499+ .fixed_int = > | info | {
1500+ // TODO: std.math.big.int does not have a negateWrap method
1501+ _ = info ;
1502+ return null ;
1503+ },
1504+ },
1505+ else = > unreachable ,
1506+ }
1507+ return try analyser .resolveIntegerExpressionResult (ty , result .toConst ());
1508+ }
1509+
1510+ fn resolveBinaryIntegerExpression (
1511+ analyser : * Analyser ,
1512+ tag : std.zig.Ast.Node.Tag ,
1513+ instance : Type ,
1514+ lhs_instance : Type ,
1515+ rhs_instance : Type ,
1516+ ) ! ? Type {
1517+ const lhs_index = lhs_instance .ipIndex () orelse return null ;
1518+ const rhs_index = rhs_instance .ipIndex () orelse return null ;
1519+ const type_of = try instance .typeOf (analyser );
1520+ const ty = type_of .ipIndex () orelse return null ;
1521+ const int_info = analyser .intInfo (ty ) orelse return null ;
1522+ var lhs = try analyser .ip .toBigInt (analyser .gpa , lhs_index ) orelse return null ;
1523+ defer lhs .deinit ();
1524+ var rhs = try analyser .ip .toBigInt (analyser .gpa , rhs_index ) orelse return null ;
1525+ defer rhs .deinit ();
1526+ var result : std.math.big.int.Managed = try .init (analyser .gpa );
1527+ defer result .deinit ();
1528+ switch (tag ) {
1529+ .mul = > try result .mul (& lhs , & rhs ),
1530+ .div = > {
1531+ var temp : std.math.big.int.Managed = try .init (analyser .gpa );
1532+ defer temp .deinit ();
1533+ try result .divTrunc (& temp , & lhs , & rhs );
1534+ },
1535+ .mod = > {
1536+ var temp : std.math.big.int.Managed = try .init (analyser .gpa );
1537+ defer temp .deinit ();
1538+ try temp .divTrunc (& result , & lhs , & rhs );
1539+ },
1540+ .add = > try result .add (& lhs , & rhs ),
1541+ .sub = > try result .sub (& lhs , & rhs ),
1542+ .shl = > try result .shiftLeft (& lhs , rhs .toInt (usize ) catch return null ),
1543+ .shr = > try result .shiftRight (& lhs , rhs .toInt (usize ) catch return null ),
1544+ .bit_and = > try result .bitAnd (& lhs , & rhs ),
1545+ .bit_xor = > try result .bitXor (& lhs , & rhs ),
1546+ .bit_or = > try result .bitOr (& lhs , & rhs ),
1547+ .add_wrap ,
1548+ .sub_wrap ,
1549+ .mul_wrap ,
1550+ .add_sat ,
1551+ .sub_sat ,
1552+ .mul_sat ,
1553+ .shl_sat ,
1554+ = > switch (int_info ) {
1555+ .comptime_int = > switch (tag ) {
1556+ .add_wrap , .add_sat = > try result .add (& lhs , & rhs ),
1557+ .sub_wrap , .sub_sat = > try result .sub (& lhs , & rhs ),
1558+ .mul_wrap , .mul_sat = > try result .mul (& lhs , & rhs ),
1559+ .shl_sat = > try result .shiftLeft (& lhs , rhs .toInt (usize ) catch return null ),
1560+ else = > unreachable ,
1561+ },
1562+ .fixed_int = > | info | switch (tag ) {
1563+ .add_wrap = > _ = try result .addWrap (& lhs , & rhs , info .signedness , info .bits ),
1564+ .sub_wrap = > _ = try result .subWrap (& lhs , & rhs , info .signedness , info .bits ),
1565+ .mul_wrap = > _ = try result .mulWrap (& lhs , & rhs , info .signedness , info .bits ),
1566+ .add_sat = > try result .addSat (& lhs , & rhs , info .signedness , info .bits ),
1567+ .sub_sat = > try result .subSat (& lhs , & rhs , info .signedness , info .bits ),
1568+ .mul_sat = > {
1569+ // std.math.big.int does not have a mulSat method
1570+ try result .mul (& lhs , & rhs );
1571+ try result .saturate (& result , info .signedness , info .bits );
1572+ },
1573+ .shl_sat = > try result .shiftLeftSat (& lhs , rhs .toInt (usize ) catch return null , info .signedness , info .bits ),
1574+ else = > unreachable ,
1575+ },
1576+ },
1577+ else = > unreachable ,
1578+ }
1579+ return try analyser .resolveIntegerExpressionResult (ty , result .toConst ());
1580+ }
1581+
1582+ fn resolveIntegerExpressionResult (
1583+ analyser : * Analyser ,
1584+ ty : InternPool.Index ,
1585+ result : std.math.big.int.Const ,
1586+ ) ! ? Type {
1587+ const int_info = analyser .intInfo (ty ) orelse return null ;
1588+ switch (int_info ) {
1589+ .comptime_int = > {},
1590+ .fixed_int = > | info | {
1591+ if (! result .fitsInTwosComp (info .signedness , info .bits )) {
1592+ return null ;
1593+ }
1594+ },
1595+ }
1596+ const index = index : {
1597+ if (result .positive ) blk : {
1598+ const int = result .toInt (u64 ) catch break :blk ;
1599+ break :index try analyser .ip .get (.{ .int_u64_value = .{ .ty = ty , .int = int } });
1600+ } else blk : {
1601+ const int = result .toInt (i64 ) catch break :blk ;
1602+ break :index try analyser .ip .get (.{ .int_i64_value = .{ .ty = ty , .int = int } });
1603+ }
1604+ break :index try analyser .ip .getBigInt (ty , result );
1605+ };
1606+ return Type .fromIP (analyser , ty , index );
1607+ }
1608+
14671609const primitives : std .StaticStringMap (InternPool .Index ) = .initComptime (.{
14681610 .{ "anyerror" , .anyerror_type },
14691611 .{ "anyframe" , .anyframe_type },
@@ -1982,8 +2124,9 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
19822124 const node = node_handle .node ;
19832125 const handle = node_handle .handle ;
19842126 const tree = & handle .tree ;
2127+ const node_tag = tree .nodeTag (node );
19852128
1986- switch (tree . nodeTag ( node ) ) {
2129+ switch (node_tag ) {
19872130 .global_var_decl ,
19882131 .local_var_decl ,
19892132 .simple_var_decl ,
@@ -2754,7 +2897,7 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
27542897 = > {
27552898 const ty = try analyser .resolveTypeOfNodeInternal (.of (tree .nodeData (node ).node , handle )) orelse return null ;
27562899 if (ty .is_type_val ) return null ;
2757- return ty .withoutIPIndex (analyser );
2900+ return try analyser . resolveUnaryIntegerExpression ( node_tag , ty ) orelse ty .withoutIPIndex (analyser );
27582901 },
27592902
27602903 .multiline_string_literal = > {
@@ -2899,63 +3042,69 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) Error
28993042 .bit_or ,
29003043 = > {
29013044 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2902- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2903- if (lhs_ty .is_type_val ) return null ;
2904- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2905- if (rhs_ty .is_type_val ) return null ;
2906- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2907- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2908- return analyser .resolvePeerTypes (lhs_ty , rhs_ty );
3045+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
3046+ if (lhs_instance .is_type_val ) return null ;
3047+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
3048+ if (rhs_instance .is_type_val ) return null ;
3049+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
3050+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
3051+ const instance = try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ) orelse return null ;
3052+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
29093053 },
29103054
29113055 .add = > {
29123056 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2913- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2914- if (lhs_ty .is_type_val ) return null ;
2915- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2916- if (rhs_ty .is_type_val ) return null ;
2917- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2918- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2919- if (lhs_ty .pointerSize (analyser )) | lhs_size | {
3057+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
3058+ if (lhs_instance .is_type_val ) return null ;
3059+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
3060+ if (rhs_instance .is_type_val ) return null ;
3061+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
3062+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
3063+ if (lhs_no_value .pointerSize (analyser )) | lhs_size | {
29203064 return switch (lhs_size ) {
2921- .many , .c = > lhs_ty ,
3065+ .many , .c = > lhs_no_value ,
29223066 else = > null ,
29233067 };
29243068 }
2925- return try analyser .resolvePeerTypes (lhs_ty , rhs_ty );
3069+ const instance = try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ) orelse return null ;
3070+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
29263071 },
29273072
29283073 .sub = > {
29293074 const lhs , const rhs = tree .nodeData (node ).node_and_node ;
2930- var lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2931- if (lhs_ty .is_type_val ) return null ;
2932- var rhs_ty = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
2933- if (rhs_ty .is_type_val ) return null ;
2934- lhs_ty = lhs_ty .withoutIPIndex (analyser );
2935- rhs_ty = rhs_ty .withoutIPIndex (analyser );
2936- if (lhs_ty .pointerSize (analyser )) | lhs_size | {
2937- if (rhs_ty .pointerSize (analyser )) | rhs_size | {
3075+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
3076+ if (lhs_instance .is_type_val ) return null ;
3077+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return null ;
3078+ if (rhs_instance .is_type_val ) return null ;
3079+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
3080+ const rhs_no_value = rhs_instance .withoutIPIndex (analyser );
3081+ if (lhs_no_value .pointerSize (analyser )) | lhs_size | {
3082+ if (rhs_no_value .pointerSize (analyser )) | rhs_size | {
29383083 if (lhs_size == .slice ) return null ;
29393084 if (rhs_size == .slice ) return null ;
29403085 return Type .fromIP (analyser , .usize_type , null );
29413086 } else {
29423087 return switch (lhs_size ) {
2943- .many , .c = > lhs_ty ,
3088+ .many , .c = > lhs_no_value ,
29443089 else = > null ,
29453090 };
29463091 }
29473092 }
2948- return try analyser .resolvePeerTypes (lhs_ty , rhs_ty );
3093+ const instance = try analyser .resolvePeerTypes (lhs_no_value , rhs_no_value ) orelse return null ;
3094+ return try analyser .resolveBinaryIntegerExpression (node_tag , instance , lhs_instance , rhs_instance ) orelse return instance ;
29493095 },
29503096
29513097 .shl ,
29523098 .shl_sat ,
29533099 .shr ,
29543100 = > {
2955- const lhs , _ = tree .nodeData (node ).node_and_node ;
2956- const lhs_ty = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
2957- if (lhs_ty .is_type_val ) return null ;
2958- return lhs_ty .withoutIPIndex (analyser );
3101+ const lhs , const rhs = tree .nodeData (node ).node_and_node ;
3102+ const lhs_instance = try analyser .resolveTypeOfNodeInternal (.of (lhs , handle )) orelse return null ;
3103+ if (lhs_instance .is_type_val ) return null ;
3104+ const lhs_no_value = lhs_instance .withoutIPIndex (analyser );
3105+ const rhs_instance = try analyser .resolveTypeOfNodeInternal (.of (rhs , handle )) orelse return lhs_no_value ;
3106+ if (rhs_instance .is_type_val ) return lhs_no_value ;
3107+ return try analyser .resolveBinaryIntegerExpression (node_tag , lhs_no_value , lhs_instance , rhs_instance ) orelse return lhs_no_value ;
29593108 },
29603109
29613110 .array_mult = > {
0 commit comments