Repository: GridTools/gt4py
Pull request #1255 (2023-05-22 11:54:07)

feature[next]: Remove int type from FOAST, PAST, ITIR
This PR removes all occurrences of the `int`, `float` type and replaces them by the fixed size types `int32`, `int64`, `float32`, `float64`. In particular `int` was problematic as an undetermined size lead to problems in type inference giving strange errors akin of `Can not satisfy constraint on primitive types: int ≡ int32`.

Blocked by #1258 (already merged in this PR).

tehrengruber: @havogt Mostly as discussed. I have introduced a new function `literal_from_value` in `ir_makers` and left `literal` as is. Since `literal_from_value` does not itself introduce any new logic it made sense to me to leave it in `ir_makers` which contains other functions with similar tasks (i.e. `ensure_expr`).

Patch:
diff --git a/src/gt4py/next/ffront/fbuiltins.py b/src/gt4py/next/ffront/fbuiltins.py
index 2d4e6e78..919b49c1 100644
--- a/src/gt4py/next/ffront/fbuiltins.py
+++ b/src/gt4py/next/ffront/fbuiltins.py
@@ -14,6 +14,7 @@
 
 from builtins import bool, float, int, tuple
 from dataclasses import dataclass
+from typing import TypeAlias
 
 from numpy import float32, float64, int32, int64
 
@@ -29,6 +30,12 @@ PYTHON_TYPE_BUILTIN_NAMES = [t.__name__ for t in PYTHON_TYPE_BUILTINS]
 TYPE_BUILTINS = [Field, Dimension, int32, int64, float32, float64] + PYTHON_TYPE_BUILTINS
 TYPE_BUILTIN_NAMES = [t.__name__ for t in TYPE_BUILTINS]
 
+# Be aware: Type aliases are not fully supported in the frontend yet, e.g. `IndexType(1)` will not
+# work.
+IndexType: TypeAlias = int32
+
+TYPE_ALIAS_NAMES = ["IndexType"]
+
 
 @dataclass
 class BuiltInFunction:
@@ -200,7 +207,7 @@ BUILTIN_NAMES = TYPE_BUILTIN_NAMES + FUN_BUILTIN_NAMES
 
 BUILTINS = {name: globals()[name] for name in BUILTIN_NAMES}
 
-__all__ = [*(set(BUILTIN_NAMES) - {"Dimension", "Field"})]
+__all__ = [*((set(BUILTIN_NAMES) | set(TYPE_ALIAS_NAMES)) - {"Dimension", "Field"})]
 
 
 # TODO(tehrengruber): FieldOffset and runtime.Offset are not an exact conceptual
diff --git a/src/gt4py/next/ffront/foast_pretty_printer.py b/src/gt4py/next/ffront/foast_pretty_printer.py
index b3f299fd..56e5afb8 100644
--- a/src/gt4py/next/ffront/foast_pretty_printer.py
+++ b/src/gt4py/next/ffront/foast_pretty_printer.py
@@ -225,14 +225,14 @@ def pretty_format(node: foast.LocatedNode) -> str:
     """
     Pretty print (to string) an `foast.LocatedNode`.
 
-    >>> from gt4py.next import Field, Dimension, field_operator
+    >>> from gt4py.next import Field, Dimension, field_operator, float64
     >>> IDim = Dimension("IDim")
     >>> @field_operator
-    ... def field_op(a: Field[[IDim], int]) -> Field[[IDim], int]:
-    ...     return a+1
+    ... def field_op(a: Field[[IDim], float64]) -> Field[[IDim], float64]:
+    ...     return a + 1.0
     >>> print(pretty_format(field_op.foast_node))
     @field_operator
-    def field_op(a: Field[[IDim], int64]) -> Field[[IDim], int64]:
-      return a + 1
+    def field_op(a: Field[[IDim], float64]) -> Field[[IDim], float64]:
+      return a + 1.0
     """
     return _PrettyPrinter().apply(node)
diff --git a/src/gt4py/next/ffront/past_to_itir.py b/src/gt4py/next/ffront/past_to_itir.py
index 98fd1cfa..0b68c18c 100644
--- a/src/gt4py/next/ffront/past_to_itir.py
+++ b/src/gt4py/next/ffront/past_to_itir.py
@@ -155,9 +155,8 @@ class ProgramLowering(traits.VisitorWithSymbolTableTrait, NodeTranslator):
         if slice_bound is None:
             lowered_bound = default_value
         elif isinstance(slice_bound, past.Constant):
-            assert (
-                isinstance(slice_bound.type, ts.ScalarType)
-                and slice_bound.type.kind == ts.ScalarKind.INT
+            assert isinstance(slice_bound.type, ts.ScalarType) and type_info.is_integral(
+                slice_bound.type
             )
             if slice_bound.value < 0:
                 lowered_bound = itir.FunCall(
@@ -217,7 +216,7 @@ class ProgramLowering(traits.VisitorWithSymbolTableTrait, NodeTranslator):
             else:
                 lower = self._visit_slice_bound(
                     slices[dim_i].lower if slices else None,
-                    itir.Literal(value="0", type="int"),
+                    itir.Literal(value="0", type=itir.INTEGER_INDEX_BUILTIN),
                     dim_size,
                 )
                 upper = self._visit_slice_bound(
@@ -336,8 +335,6 @@ class ProgramLowering(traits.VisitorWithSymbolTableTrait, NodeTranslator):
                         f"Scalars of kind {node.type.kind} not supported currently."
                     )
             typename = node.type.kind.name.lower()
-            if typename.startswith("int"):
-                typename = "int"
             return itir.Literal(value=str(node.value), type=typename)
 
         raise NotImplementedError("Only scalar literals supported currently.")
diff --git a/src/gt4py/next/iterator/builtins.py b/src/gt4py/next/iterator/builtins.py
index dabf814f..58dd5b8b 100644
--- a/src/gt4py/next/iterator/builtins.py
+++ b/src/gt4py/next/iterator/builtins.py
@@ -388,7 +388,7 @@ UNARY_MATH_FP_BUILTINS = {
 }
 UNARY_MATH_FP_PREDICATE_BUILTINS = {"isfinite", "isinf", "isnan"}
 BINARY_MATH_NUMBER_BUILTINS = {"minimum", "maximum", "fmod", "power"}
-TYPEBUILTINS = {"int", "int32", "int64", "float", "float32", "float64", "bool"}
+TYPEBUILTINS = {"int32", "int64", "float32", "float64", "bool"}
 MATH_BUILTINS = (
     UNARY_MATH_NUMBER_BUILTINS
     | UNARY_MATH_FP_BUILTINS
diff --git a/src/gt4py/next/iterator/embedded.py b/src/gt4py/next/iterator/embedded.py
index fea6e2be..e92cfb45 100644
--- a/src/gt4py/next/iterator/embedded.py
+++ b/src/gt4py/next/iterator/embedded.py
@@ -48,7 +48,7 @@ import numpy.typing as npt
 
 from gt4py.eve import extended_typing as xtyping
 from gt4py.next import common
-from gt4py.next.iterator import builtins, runtime, utils
+from gt4py.next.iterator import builtins, runtime
 
 
 EMBEDDED = "embedded"
@@ -143,6 +143,13 @@ def is_int_index(p: Any) -> TypeGuard[IntIndex]:
     return isinstance(p, (int, np.integer))
 
 
+def _tupelize(tup):
+    if isinstance(tup, tuple):
+        return tup
+    else:
+        return (tup,)
+
+
 @runtime_checkable
 class ItIterator(Protocol):
     """
@@ -892,7 +899,7 @@ class LocatedFieldImpl(MutableLocatedField):
 
     # TODO in a stable implementation of the Field concept we should make this behavior the default behavior for __getitem__
     def field_getitem(self, indices: FieldIndexOrIndices) -> Any:
-        indices = utils.tupelize(indices)
+        indices = _tupelize(indices)
         return self.getter(indices)
 
     def __setitem__(self, indices: ArrayIndexOrIndices, value: Any):
@@ -1008,7 +1015,7 @@ def np_as_located_field(
             offsets = None
 
         def setter(indices, value):
-            indices = utils.tupelize(indices)
+            indices = _tupelize(indices)
             a[_shift_field_indices(indices, offsets) if offsets else indices] = value
 
         def getter(indices):
diff --git a/src/gt4py/next/iterator/ir.py b/src/gt4py/next/iterator/ir.py
index a28f40e9..bd712f9f 100644
--- a/src/gt4py/next/iterator/ir.py
+++ b/src/gt4py/next/iterator/ir.py
@@ -168,8 +168,10 @@ BINARY_LOGICAL_BUILTINS = {
     "xor_",
 }
 
-INTEGER_BUILTINS = {"int", "int32", "int64"}
-FLOATING_POINT_BUILTINS = {"float", "float32", "float64"}
+#: builtin / dtype used to construct integer indices, like domain bounds
+INTEGER_INDEX_BUILTIN = "int32"
+INTEGER_BUILTINS = {"int32", "int64"}
+FLOATING_POINT_BUILTINS = {"float32", "float64"}
 TYPEBUILTINS = {*INTEGER_BUILTINS, *FLOATING_POINT_BUILTINS, "bool"}
 
 GRAMMAR_BUILTINS = {
diff --git a/src/gt4py/next/iterator/ir_makers.py b/src/gt4py/next/iterator/ir_makers.py
index 8fec9aaa..9eb45fbf 100644
--- a/src/gt4py/next/iterator/ir_makers.py
+++ b/src/gt4py/next/iterator/ir_makers.py
@@ -14,7 +14,9 @@
 
 from typing import Callable, Union
 
+from gt4py.next import common
 from gt4py.next.iterator import ir as itir
+from gt4py.next.type_system import type_specifications as ts, type_translation
 
 
 def sym(sym_or_name: Union[str, itir.Sym]) -> itir.Sym:
@@ -51,7 +53,7 @@ def ref(ref_or_name: Union[str, itir.SymRef]) -> itir.SymRef:
     return itir.SymRef(id=ref_or_name)
 
 
-def ensure_expr(literal_or_expr: Union[str, int, itir.Expr]) -> itir.Expr:
+def ensure_expr(literal_or_expr: Union[str, common.Scalar, itir.Expr]) -> itir.Expr:
     """
     Convert literals into a SymRef or Literal and let expressions pass unchanged.
 
@@ -61,18 +63,16 @@ def ensure_expr(literal_or_expr: Union[str, int, itir.Expr]) -> itir.Expr:
     SymRef(id=SymbolRef('a'))
 
     >>> ensure_expr(3)
-    Literal(value='3', type='int')
+    Literal(value='3', type='int32')
 
     >>> ensure_expr(itir.OffsetLiteral(value="i"))
     OffsetLiteral(value='i')
     """
     if isinstance(literal_or_expr, str):
         return ref(literal_or_expr)
-    elif isinstance(literal_or_expr, int):
-        return itir.Literal(value=str(literal_or_expr), type="int")
-    elif isinstance(literal_or_expr, float):
-        return itir.Literal(value=str(literal_or_expr), type="float")
-    return literal_or_expr
+    elif isinstance(literal_or_expr, common.Scalar):  # type: ignore[arg-type] # mypy bug #11673
+        return literal_from_value(literal_or_expr)  # type: ignore[arg-type] # mypy bug #11673
+    return literal_or_expr  # type: ignore[return-value] # mypy bug #11673
 
 
 def ensure_offset(str_or_offset: Union[str, int, itir.OffsetLiteral]) -> itir.OffsetLiteral:
@@ -116,7 +116,7 @@ class call:
     Examples
     --------
     >>> call("plus")(1, 1)
-    FunCall(fun=SymRef(id=SymbolRef('plus')), args=[Literal(value='1', type='int'), Literal(value='1', type='int')])
+    FunCall(fun=SymRef(id=SymbolRef('plus')), args=[Literal(value='1', type='int32'), Literal(value='1', type='int32')])
     """
 
     def __init__(self, expr):
@@ -218,9 +218,9 @@ def make_tuple(*args):
     return call("make_tuple")(*args)
 
 
-def tuple_get(index, tuple_expr):
+def tuple_get(index: str | int, tuple_expr):
     """Create a tuple_get FunCall, shorthand for ``call("tuple_get")(index, tuple_expr)``."""
-    return call("tuple_get")(index, tuple_expr)
+    return call("tuple_get")(literal(str(index), itir.INTEGER_INDEX_BUILTIN), tuple_expr)
 
 
 def if_(cond, true_val, false_val):
@@ -275,6 +275,35 @@ def literal(value: str, typename: str):
     return itir.Literal(value=value, type=typename)
 
 
+def literal_from_value(val: common.Scalar) -> itir.Literal:
+    """
+    Make a literal node from a value.
+
+    >>> literal_from_value(1.)
+    Literal(value='1.0', type='float64')
+    >>> literal_from_value(1)
+    Literal(value='1', type='int32')
+    >>> literal_from_value(2147483648)
+    Literal(value='2147483648', type='int64')
+    >>> literal_from_value(True)
+    Literal(value='True', type='bool')
+    """
+    if not isinstance(val, common.Scalar):  # type: ignore[arg-type] # mypy bug #11673
+        raise ValueError(f"Value must be a scalar, but got {type(val).__name__}")
+
+    # At the time this has been written the iterator module has its own type system that is
+    # uncoupled from the one used in the frontend. However since we decided to eventually replace
+    # it with the frontend type system we already use it here (avoiding unnecessary code
+    # duplication).
+    type_spec = type_translation.from_value(val)
+    assert isinstance(type_spec, ts.ScalarType)
+
+    typename = type_spec.kind.name.lower()
+    assert typename in itir.TYPEBUILTINS
+
+    return itir.Literal(value=str(val), type=typename)
+
+
 def neighbors(offset, it):
     offset = ensure_offset(offset)
     return call("neighbors")(offset, it)
diff --git a/src/gt4py/next/iterator/pretty_parser.py b/src/gt4py/next/iterator/pretty_parser.py
index 1e21d220..a541e985 100644
--- a/src/gt4py/next/iterator/pretty_parser.py
+++ b/src/gt4py/next/iterator/pretty_parser.py
@@ -16,7 +16,7 @@ from typing import Union
 
 from lark import lark, lexer as lark_lexer, visitors as lark_visitors
 
-from gt4py.next.iterator import ir
+from gt4py.next.iterator import ir, ir_makers as im
 
 
 GRAMMAR = """
@@ -98,10 +98,10 @@ class ToIrTransformer(lark_visitors.Transformer):
         return ir.SymRef(id=value.value)
 
     def INT_LITERAL(self, value: lark_lexer.Token) -> ir.Literal:
-        return ir.Literal(value=value.value, type="int")
+        return im.literal_from_value(int(value.value))
 
     def FLOAT_LITERAL(self, value: lark_lexer.Token) -> ir.Literal:
-        return ir.Literal(value=value.value, type="float")
+        return ir.Literal(value=value.value, type="float64")
 
     def OFFSET_LITERAL(self, value: lark_lexer.Token) -> ir.OffsetLiteral:
         v: Union[int, str] = value.value[:-1]
diff --git a/src/gt4py/next/iterator/tracing.py b/src/gt4py/next/iterator/tracing.py
index 6d510fb3..4a96c8f4 100644
--- a/src/gt4py/next/iterator/tracing.py
+++ b/src/gt4py/next/iterator/tracing.py
@@ -17,8 +17,8 @@ import inspect
 from typing import List
 
 from gt4py.eve import Node
-from gt4py.next import iterator
-from gt4py.next.iterator import builtins
+from gt4py.next import common, iterator
+from gt4py.next.iterator import builtins, ir_makers as im
 from gt4py.next.iterator.ir import (
     AxisLiteral,
     Expr,
@@ -26,7 +26,6 @@ from gt4py.next.iterator.ir import (
     FunCall,
     FunctionDefinition,
     Lambda,
-    Literal,
     NoneLiteral,
     OffsetLiteral,
     StencilClosure,
@@ -152,12 +151,8 @@ def make_node(o):
             return lambdadef(o)
     if isinstance(o, iterator.runtime.Offset):
         return OffsetLiteral(value=o.value)
-    if isinstance(o, bool):
-        return Literal(value=str(o), type="bool")
-    if isinstance(o, int):
-        return Literal(value=str(o), type="int")
-    if isinstance(o, float):
-        return Literal(value=str(o), type="float")
+    if isinstance(o, common.Scalar):
+        return im.literal_from_value(o)
     if isinstance(o, CartesianAxis):
         return AxisLiteral(value=o.value)
     if isinstance(o, tuple):
diff --git a/src/gt4py/next/iterator/transforms/global_tmps.py b/src/gt4py/next/iterator/transforms/global_tmps.py
index e69c95e1..b553dc76 100644
--- a/src/gt4py/next/iterator/transforms/global_tmps.py
+++ b/src/gt4py/next/iterator/transforms/global_tmps.py
@@ -237,12 +237,12 @@ def _named_range_with_offsets(
     if lower_offset:
         lower_bound = ir.FunCall(
             fun=ir.SymRef(id="plus"),
-            args=[lower_bound, ir.Literal(value=str(lower_offset), type="int")],
+            args=[lower_bound, ir.Literal(value=str(lower_offset), type=ir.INTEGER_INDEX_BUILTIN)],
         )
     if upper_offset:
         upper_bound = ir.FunCall(
             fun=ir.SymRef(id="plus"),
-            args=[upper_bound, ir.Literal(value=str(upper_offset), type="int")],
+            args=[upper_bound, ir.Literal(value=str(upper_offset), type=ir.INTEGER_INDEX_BUILTIN)],
         )
     return ir.FunCall(
         fun=ir.SymRef(id="named_range"), args=[axis_literal, lower_bound, upper_bound]
@@ -343,8 +343,8 @@ def _unstructured_domain(
                 fun=ir.SymRef(id="named_range"),
                 args=[
                     ir.AxisLiteral(value=axis),
-                    ir.Literal(value="0", type="int"),
-                    ir.Literal(value=str(size), type="int"),
+                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
+                    ir.Literal(value=str(size), type=ir.INTEGER_INDEX_BUILTIN),
                 ],
             )
         ]
diff --git a/src/gt4py/next/iterator/type_inference.py b/src/gt4py/next/iterator/type_inference.py
index 680ef245..28422a47 100644
--- a/src/gt4py/next/iterator/type_inference.py
+++ b/src/gt4py/next/iterator/type_inference.py
@@ -281,6 +281,22 @@ class Primitive(Type):
         return True
 
 
+class UnionPrimitive(Type):
+    """Union of primitive types."""
+
+    names: tuple[str, ...]
+
+    def handle_constraint(
+        self, other: Type, add_constraint: abc.Callable[[Type, Type], None]
+    ) -> bool:
+        if isinstance(other, UnionPrimitive):
+            raise AssertionError("`UnionPrimitive` may only appear on one side of a constraint.")
+        if not isinstance(other, Primitive):
+            return False
+
+        return other.name in self.names
+
+
 class Value(Type):
     """Marker for values."""
 
@@ -339,9 +355,16 @@ class LetPolymorphic(Type):
     dtype: Type
 
 
+def _default_constraints():
+    return {
+        (FLOAT_DTYPE, UnionPrimitive(names=("float32", "float64"))),
+        (INT_DTYPE, UnionPrimitive(names=("int32", "int64"))),
+    }
+
+
 BOOL_DTYPE = Primitive(name="bool")
-INT_DTYPE = Primitive(name="int")
-FLOAT_DTYPE = Primitive(name="float")
+INT_DTYPE = TypeVar.fresh()
+FLOAT_DTYPE = TypeVar.fresh()
 AXIS_DTYPE = Primitive(name="axis")
 NAMED_RANGE_DTYPE = Primitive(name="named_range")
 DOMAIN_DTYPE = Primitive(name="domain")
@@ -555,7 +578,7 @@ class _TypeInferrer(eve.traits.VisitorWithSymbolTableTrait, eve.NodeTranslator):
 
     offset_provider: Optional[dict[str, Connectivity | gtx.Dimension]]
     collected_types: dict[int, Type] = dataclasses.field(default_factory=dict)
-    constraints: set[tuple[Type, Type]] = dataclasses.field(default_factory=set)
+    constraints: set[tuple[Type, Type]] = dataclasses.field(default_factory=_default_constraints)
 
     def visit(self, node, **kwargs) -> typing.Any:
         result = super().visit(node, **kwargs)
@@ -654,8 +677,13 @@ class _TypeInferrer(eve.traits.VisitorWithSymbolTableTrait, eve.NodeTranslator):
         # Calls to `tuple_get` are handled as being part of the grammar, not as function calls.
         if len(node.args) != 2:
             raise TypeError("`tuple_get` requires exactly two arguments.")
-        if not isinstance(node.args[0], ir.Literal) or node.args[0].type != "int":
-            raise TypeError("The first argument to `tuple_get` must be a literal int.")
+        if (
+            not isinstance(node.args[0], ir.Literal)
+            or node.args[0].type != ir.INTEGER_INDEX_BUILTIN
+        ):
+            raise TypeError(
+                f"The first argument to `tuple_get` must be a literal of type `{ir.INTEGER_INDEX_BUILTIN}`."
+            )
         self.visit(node.args[0], **kwargs)  # visit index so that its type is collected
         idx = int(node.args[0].value)
         tup = self.visit(node.args[1], **kwargs)
diff --git a/src/gt4py/next/iterator/utils.py b/src/gt4py/next/iterator/utils.py
deleted file mode 100644
index 92474bc5..00000000
--- a/src/gt4py/next/iterator/utils.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# GT4Py - GridTools Framework
-#
-# Copyright (c) 2014-2023, ETH Zurich
-# All rights reserved.
-#
-# This file is part of the GT4Py project and the GridTools framework.
-# GT4Py is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or any later
-# version. See the LICENSE.txt file at the top-level directory of this
-# distribution for a copy of the license or check <https://www.gnu.org/licenses/>.
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-
-def tupelize(tup):
-    if isinstance(tup, tuple):
-        return tup
-    else:
-        return (tup,)
diff --git a/src/gt4py/next/otf/binding/cpp_interface.py b/src/gt4py/next/otf/binding/cpp_interface.py
index 1c18f812..5f7c4225 100644
--- a/src/gt4py/next/otf/binding/cpp_interface.py
+++ b/src/gt4py/next/otf/binding/cpp_interface.py
@@ -41,8 +41,6 @@ def render_scalar_type(scalar_type: ts.ScalarType) -> str:
             return "double"
         case ts.ScalarKind.STRING:
             return "std::string"
-        case ts.ScalarKind.DIMENSION:
-            raise AssertionError(f"Deprecated type '{scalar_type}' is not supported.")
         case _:
             raise AssertionError(
                 f"Scalar kind '{scalar_type}' is not implemented when it should be."
diff --git a/src/gt4py/next/program_processors/codegens/gtfn/codegen.py b/src/gt4py/next/program_processors/codegens/gtfn/codegen.py
index e8733585..5d463a02 100644
--- a/src/gt4py/next/program_processors/codegens/gtfn/codegen.py
+++ b/src/gt4py/next/program_processors/codegens/gtfn/codegen.py
@@ -56,10 +56,8 @@ class GTFNCodegen(codegen.TemplatedGenerator):
         "maximum": "std::max",
         "fmod": "std::fmod",
         "power": "std::pow",
-        "float": "double",
         "float32": "float",
         "float64": "double",
-        "int": "long",
         "int32": "std::int32_t",
         "int64": "std::int64_t",
         "bool": "bool",
diff --git a/src/gt4py/next/program_processors/codegens/gtfn/itir_to_gtfn_ir.py b/src/gt4py/next/program_processors/codegens/gtfn/itir_to_gtfn_ir.py
index 63701a63..f78a0526 100644
--- a/src/gt4py/next/program_processors/codegens/gtfn/itir_to_gtfn_ir.py
+++ b/src/gt4py/next/program_processors/codegens/gtfn/itir_to_gtfn_ir.py
@@ -51,10 +51,8 @@ from gt4py.next.program_processors.codegens.gtfn.gtfn_ir_common import Expr, Nod
 def pytype_to_cpptype(t: str):
     try:
         return {
-            "float": "double",
             "float32": "float",
             "float64": "double",
-            "int": "long",
             "int32": "std::int32_t",
             "int64": "std::int64_t",
             "bool": "bool",
diff --git a/src/gt4py/next/type_inference.py b/src/gt4py/next/type_inference.py
index b6a74998..f06b26e4 100644
--- a/src/gt4py/next/type_inference.py
+++ b/src/gt4py/next/type_inference.py
@@ -164,6 +164,14 @@ class _Dedup(eve.NodeTranslator):
         return node
 
 
+def _assert_constituent_types(value: typing.Any, allowed_types: tuple[type, ...]) -> None:
+    if isinstance(value, tuple):
+        for el in value:
+            _assert_constituent_types(el, allowed_types)
+    else:
+        assert isinstance(value, allowed_types)
+
+
 class _Renamer:
     """Efficiently rename (that is, replace) nodes in a type expression.
 
@@ -191,7 +199,7 @@ class _Renamer:
                     self._parents.setdefault(child, []).append((node, typing.cast(str, field)))
                     collect_parents(child)
                 else:
-                    assert isinstance(child, (int, str))
+                    _assert_constituent_types(child, (int, str))
 
         collect_parents(dtype)
 
diff --git a/src/gt4py/next/type_system/type_info.py b/src/gt4py/next/type_system/type_info.py
index 1f0f6d10..5024e0fe 100644
--- a/src/gt4py/next/type_system/type_info.py
+++ b/src/gt4py/next/type_system/type_info.py
@@ -68,7 +68,7 @@ def primitive_constituents(
 
     >>> from gt4py.next import Dimension
     >>> I = Dimension(value="I")
-    >>> int_type = ts.ScalarType(kind=ts.ScalarKind.INT)
+    >>> int_type = ts.ScalarType(kind=ts.ScalarKind.INT64)
     >>> field_type = ts.FieldType(dims=[I], dtype=int_type)
 
     >>> tuple_type = ts.TupleType(types=[int_type, field_type])
@@ -100,7 +100,7 @@ def apply_to_primitive_constituents(
     """
     Apply function to all primitive constituents of a type.
 
-    >>> int_type = ts.ScalarType(kind=ts.ScalarKind.INT)
+    >>> int_type = ts.ScalarType(kind=ts.ScalarKind.INT64)
     >>> tuple_type = ts.TupleType(types=[int_type, int_type])
     >>> print(apply_to_primitive_constituents(tuple_type, lambda primitive_type: ts.FieldType(dims=[], dtype=primitive_type)))
     tuple[Field[[], int64], Field[[], int64]]
@@ -169,17 +169,14 @@ def is_integral(symbol_type: ts.TypeSpec) -> bool:
 
     Examples:
     ---------
-    >>> is_integral(ts.ScalarType(kind=ts.ScalarKind.INT))
-    True
     >>> is_integral(ts.ScalarType(kind=ts.ScalarKind.INT32))
     True
     >>> is_integral(ts.ScalarType(kind=ts.ScalarKind.FLOAT32))
     False
-    >>> is_integral(ts.FieldType(dims=[], dtype=ts.ScalarType(kind=ts.ScalarKind.INT)))
+    >>> is_integral(ts.FieldType(dims=[], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32)))
     True
     """
     return extract_dtype(symbol_type).kind in [
-        ts.ScalarKind.INT,
         ts.ScalarKind.INT32,
         ts.ScalarKind.INT64,
     ]
@@ -197,7 +194,7 @@ def is_number(symbol_type: ts.TypeSpec) -> bool:
     True
     >>> is_number(ts.ScalarType(kind=ts.ScalarKind.BOOL))
     False
-    >>> is_number(ts.FieldType(dims=[], dtype=ts.ScalarType(kind=ts.ScalarKind.INT)))
+    >>> is_number(ts.FieldType(dims=[], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64)))
     False
     """
     if not isinstance(symbol_type, ts.ScalarType):
@@ -245,7 +242,7 @@ def is_type_or_tuple_of_type(type_: ts.TypeSpec, expected_type: type | tuple) ->
 
     Examples:
     ---------
-    >>> scalar_type = ts.ScalarType(kind=ts.ScalarKind.INT)
+    >>> scalar_type = ts.ScalarType(kind=ts.ScalarKind.INT64)
     >>> field_type = ts.FieldType(dims=[], dtype=scalar_type)
     >>> is_type_or_tuple_of_type(field_type, ts.FieldType)
     True
@@ -265,7 +262,7 @@ def is_tuple_of_type(type_: ts.TypeSpec, expected_type: type | tuple) -> TypeGua
 
     Examples:
     ---------
-    >>> scalar_type = ts.ScalarType(kind=ts.ScalarKind.INT)
+    >>> scalar_type = ts.ScalarType(kind=ts.ScalarKind.INT64)
     >>> field_type = ts.FieldType(dims=[], dtype=scalar_type)
     >>> is_tuple_of_type(field_type, ts.FieldType)
     False
diff --git a/src/gt4py/next/type_system/type_specifications.py b/src/gt4py/next/type_system/type_specifications.py
index 12981e6a..10d2aa57 100644
--- a/src/gt4py/next/type_system/type_specifications.py
+++ b/src/gt4py/next/type_system/type_specifications.py
@@ -15,8 +15,6 @@
 from dataclasses import dataclass
 from typing import Optional
 
-import numpy as np
-
 from gt4py.eve.type_definitions import IntEnum
 from gt4py.next import common as func_common
 
@@ -77,12 +75,8 @@ class ScalarKind(IntEnum):
     BOOL = 1
     INT32 = 32
     INT64 = 64
-    # Python's "int" type in the Python AST should be mapped to ScalarKind.INT in our ASTs. The size, as
-    # determined by numpy, varies by platform. (Size is the same as C's "long" type.)
-    INT = INT32 if np.int_ == np.int32 else INT64
     FLOAT32 = 1032
     FLOAT64 = 1064
-    DIMENSION = 2001
     STRING = 3001
 
 
diff --git a/src/gt4py/next/type_system/type_translation.py b/src/gt4py/next/type_system/type_translation.py
index 7ffa8795..b60ea115 100644
--- a/src/gt4py/next/type_system/type_translation.py
+++ b/src/gt4py/next/type_system/type_translation.py
@@ -24,7 +24,7 @@ import numpy.typing as npt
 
 from gt4py.eve import extended_typing as xtyping
 from gt4py.next import common
-from gt4py.next.type_system import type_specifications as ts
+from gt4py.next.type_system import type_info, type_specifications as ts
 
 
 def get_scalar_kind(dtype: npt.DTypeLike) -> ts.ScalarKind:
@@ -165,6 +165,21 @@ def from_value(value: Any) -> ts.TypeSpec:
     #  we should check for the protocol in the future?
     if hasattr(value, "__gt_type__"):
         symbol_type = value.__gt_type__()
+    elif isinstance(value, int) and not isinstance(value, bool):
+        symbol_type = None
+        for candidate_type in [
+            ts.ScalarType(kind=ts.ScalarKind.INT32),
+            ts.ScalarType(kind=ts.ScalarKind.INT64),
+        ]:
+            min_val, max_val = type_info.arithmetic_bounds(candidate_type)
+            if min_val <= value <= max_val:
+                symbol_type = candidate_type
+                break
+        if not symbol_type:
+            raise common.GTTypeError(
+                f"Value `{value}` is out of range to be representable as `INT32` or `INT64`."
+            )
+        return candidate_type
     elif isinstance(value, common.Dimension):
         symbol_type = ts.DimensionType(dim=value)
     elif isinstance(value, LocatedField):
@@ -184,7 +199,7 @@ def from_value(value: Any) -> ts.TypeSpec:
     if isinstance(symbol_type, (ts.DataType, ts.CallableType, ts.OffsetType, ts.DimensionType)):
         return symbol_type
     else:
-        raise common.GTTypeError(f"Impossible to map '{value}' value to a Symbol")
+        raise common.GTTypeError(f"Impossible to map `{value}` value to a Symbol")
 
 
 # TODO(egparedes): Add source location info (maybe subclassing FieldOperatorSyntaxError)


Test patch:
diff --git a/tests/next_tests/integration_tests/feature_tests/cases.py b/tests/next_tests/integration_tests/feature_tests/cases.py
index 685b69a0..49137808 100644
--- a/tests/next_tests/integration_tests/feature_tests/cases.py
+++ b/tests/next_tests/integration_tests/feature_tests/cases.py
@@ -50,19 +50,19 @@ from next_tests.integration_tests.feature_tests.ffront_tests.ffront_test_utils i
 
 # mypy does not accept [IDim, ...] as a type
 
-IField: TypeAlias = gtx.Field[[IDim], np.int64]  # type: ignore [valid-type]
+IField: TypeAlias = gtx.Field[[IDim], np.int32]  # type: ignore [valid-type]
 IFloatField: TypeAlias = gtx.Field[[IDim], np.float64]  # type: ignore [valid-type]
 IBoolField: TypeAlias = gtx.Field[[IDim], bool]  # type: ignore [valid-type]
-KField: TypeAlias = gtx.Field[[KDim], np.int64]  # type: ignore [valid-type]
-IJField: TypeAlias = gtx.Field[[IDim, JDim], np.int64]  # type: ignore [valid-type]
-IKField: TypeAlias = gtx.Field[[IDim, KDim], np.int64]  # type: ignore [valid-type]
+KField: TypeAlias = gtx.Field[[KDim], np.int32]  # type: ignore [valid-type]
+IJField: TypeAlias = gtx.Field[[IDim, JDim], np.int32]  # type: ignore [valid-type]
+IKField: TypeAlias = gtx.Field[[IDim, KDim], np.int32]  # type: ignore [valid-type]
 IKFloatField: TypeAlias = gtx.Field[[IDim, KDim], np.float64]  # type: ignore [valid-type]
-IJKField: TypeAlias = gtx.Field[[IDim, JDim, KDim], np.int64]  # type: ignore [valid-type]
+IJKField: TypeAlias = gtx.Field[[IDim, JDim, KDim], np.int32]  # type: ignore [valid-type]
 IJKFloatField: TypeAlias = gtx.Field[[IDim, JDim, KDim], np.float64]  # type: ignore [valid-type]
-VField: TypeAlias = gtx.Field[[Vertex], np.int64]  # type: ignore [valid-type]
-EField: TypeAlias = gtx.Field[[Edge], np.int64]  # type: ignore [valid-type]
-CField: TypeAlias = gtx.Field[[Cell], np.int64]  # type: ignore [valid-type]
-EmptyField: TypeAlias = gtx.Field[[], np.int64]  # type: ignore [valid-type]
+VField: TypeAlias = gtx.Field[[Vertex], np.int32]  # type: ignore [valid-type]
+EField: TypeAlias = gtx.Field[[Edge], np.int32]  # type: ignore [valid-type]
+CField: TypeAlias = gtx.Field[[Cell], np.int32]  # type: ignore [valid-type]
+EmptyField: TypeAlias = gtx.Field[[], np.int32]  # type: ignore [valid-type]
 
 # TODO(ricoh): unify the following with the `ffront_test_utils.reduction_setup`
 #   fixture if `ffront_test_utils.reduction_setup` is not completely superseded
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/ffront_test_utils.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/ffront_test_utils.py
index e23e93ce..c9fb3b8f 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/ffront_test_utils.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/ffront_test_utils.py
@@ -87,7 +87,8 @@ def reduction_setup():
             [6, 12, 8, 15],  # 6
             [7, 13, 6, 16],
             [8, 14, 7, 17],
-        ]
+        ],
+        dtype=gtx.IndexType,
     )
 
     c2v_arr = np.array(
@@ -100,7 +101,8 @@ def reduction_setup():
             [7, 8, 2, 1],
             [2, 0, 3, 5],
             [5, 3, 6, 8],
-        ]
+        ],
+        dtype=gtx.IndexType,
     )
 
     c2e_arr = np.array(
@@ -113,7 +115,8 @@ def reduction_setup():
             [7, 17, 1, 16],
             [2, 9, 5, 11],
             [5, 12, 8, 14],
-        ]
+        ],
+        dtype=gtx.IndexType,
     )
 
     # create e2v connectivity by inverting v2e
@@ -123,7 +126,7 @@ def reduction_setup():
         for e in v2e_arr[v]:
             e2v_arr[e].append(v)
     assert all(len(row) == 2 for row in e2v_arr)
-    e2v_arr = np.asarray(e2v_arr)
+    e2v_arr = np.asarray(e2v_arr, dtype=gtx.IndexType)
 
     yield namedtuple(
         "ReductionSetup",
@@ -160,8 +163,8 @@ def reduction_setup():
         C2V=gtx.FieldOffset("C2V", source=Vertex, target=(Cell, c2vdim)),
         C2E=gtx.FieldOffset("C2E", source=Edge, target=(Cell, c2edim)),
         # inp=gtx.index_field(edge, dtype=np.int64), # TODO enable once we support gtx.index_fields in bindings
-        inp=gtx.np_as_located_field(Edge)(np.arange(num_edges, dtype=np.int64)),
-        out=gtx.np_as_located_field(Vertex)(np.zeros([num_vertices], dtype=np.int64)),
+        inp=gtx.np_as_located_field(Edge)(np.arange(num_edges, dtype=np.int32)),
+        out=gtx.np_as_located_field(Vertex)(np.zeros([num_vertices], dtype=np.int32)),
         offset_provider={
             "V2E": gtx.NeighborTableOffsetProvider(v2e_arr, Vertex, Edge, 4),
             "E2V": gtx.NeighborTableOffsetProvider(e2v_arr, Edge, Vertex, 2, has_skip_values=False),
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_execution.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_execution.py
index f9ec300c..8ae499ac 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_execution.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_execution.py
@@ -24,6 +24,7 @@ from gt4py.next import (
     broadcast,
     float32,
     float64,
+    int32,
     int64,
     maximum,
     minimum,
@@ -175,7 +176,7 @@ def test_scalar_arg(unstructured_case):  # noqa: F811 # fixtures
     """Test scalar argument being turned into 0-dim field."""
 
     @gtx.field_operator
-    def testee(a: int) -> cases.VField:
+    def testee(a: int32) -> cases.VField:
         return broadcast(a + 1, (Vertex,))
 
     cases.verify_with_default_data(
@@ -184,7 +185,7 @@ def test_scalar_arg(unstructured_case):  # noqa: F811 # fixtures
         ref=lambda a: np.full(
             [unstructured_case.default_sizes[Vertex]],
             a + 1,
-            dtype=int,
+            dtype=int32,
         ),
         comparison=lambda a, b: np.all(a == b),
     )
@@ -192,23 +193,23 @@ def test_scalar_arg(unstructured_case):  # noqa: F811 # fixtures
 
 def test_nested_scalar_arg(unstructured_case):  # noqa: F811 # fixtures
     @gtx.field_operator
-    def testee_inner(a: int) -> cases.VField:
+    def testee_inner(a: int32) -> cases.VField:
         return broadcast(a + 1, (Vertex,))
 
     @gtx.field_operator
-    def testee(a: int) -> cases.VField:
+    def testee(a: int32) -> cases.VField:
         return testee_inner(a + 1)
 
     cases.verify_with_default_data(
         unstructured_case,
         testee,
-        ref=lambda a: np.full([unstructured_case.default_sizes[Vertex]], a + 2, dtype=int),
+        ref=lambda a: np.full([unstructured_case.default_sizes[Vertex]], a + 2, dtype=int32),
     )
 
 
 def test_scalar_arg_with_field(cartesian_case):  # noqa: F811 # fixtures
     @gtx.field_operator
-    def testee(a: cases.IJKField, b: int) -> cases.IJKField:
+    def testee(a: cases.IJKField, b: int32) -> cases.IJKField:
         tmp = b * a
         return tmp(Ioff[1])
 
@@ -228,18 +229,22 @@ def test_scalar_in_domain_spec_and_fo_call(cartesian_case):  # noqa: F811 # fixt
         )
 
     @gtx.field_operator
-    def testee_op(size: int) -> cases.IField:
+    def testee_op(size: gtx.IndexType) -> gtx.Field[[IDim], gtx.IndexType]:
         return broadcast(size, (IDim,))
 
     @gtx.program
-    def testee(size: int, out: cases.IField):
+    def testee(size: gtx.IndexType, out: gtx.Field[[IDim], gtx.IndexType]):
         testee_op(size, out=out, domain={IDim: (0, size)})
 
     size = cartesian_case.default_sizes[IDim]
     out = cases.allocate(cartesian_case, testee, "out").zeros()()
 
     cases.verify(
-        cartesian_case, testee, size, out=out, ref=np.full_like(out.array(), size, dtype=int)
+        cartesian_case,
+        testee,
+        size,
+        out=out,
+        ref=np.full_like(out.array(), size, dtype=gtx.IndexType),
     )
 
 
@@ -286,14 +291,14 @@ def test_tuple_scalar_scan(cartesian_case):  # noqa: F811 # fixtures
 
 def test_astype_int(cartesian_case):  # noqa: F811 # fixtures
     @gtx.field_operator
-    def testee(a: cases.IFloatField) -> cases.IField:
+    def testee(a: cases.IFloatField) -> gtx.Field[[IDim], int64]:
         b = astype(a, int64)
         return b
 
     cases.verify_with_default_data(
         cartesian_case,
         testee,
-        ref=lambda a: a.astype(int),
+        ref=lambda a: a.astype(int64),
         comparison=lambda a, b: np.all(a == b),
     )
 
@@ -518,7 +523,7 @@ def test_solve_triag(cartesian_case):
 @pytest.mark.parametrize("left, right", [(2, 3), (3, 2)])
 def test_ternary_operator(cartesian_case, left, right):
     @gtx.field_operator
-    def testee(a: cases.IField, b: cases.IField, left: int64, right: int64) -> cases.IField:
+    def testee(a: cases.IField, b: cases.IField, left: int32, right: int32) -> cases.IField:
         return a if left < right else b
 
     a = cases.allocate(cartesian_case, testee, "a")()
@@ -528,7 +533,7 @@ def test_ternary_operator(cartesian_case, left, right):
     cases.verify(cartesian_case, testee, a, b, left, right, out=out, ref=(a if left < right else b))
 
     @gtx.field_operator
-    def testee(left: int64, right: int64) -> cases.IField:
+    def testee(left: int32, right: int32) -> cases.IField:
         return broadcast(3, (IDim,)) if left > right else broadcast(4, (IDim,))
 
     e = np.asarray(a) if left < right else np.asarray(b)
@@ -546,7 +551,7 @@ def test_ternary_operator(cartesian_case, left, right):
 def test_ternary_operator_tuple(cartesian_case, left, right):
     @gtx.field_operator
     def testee(
-        a: cases.IField, b: cases.IField, left: int64, right: int64
+        a: cases.IField, b: cases.IField, left: int32, right: int32
     ) -> tuple[cases.IField, cases.IField]:
         return (a, b) if left < right else (b, a)
 
@@ -598,12 +603,14 @@ def test_ternary_scan(cartesian_case):
 def test_scan_nested_tuple_output(forward, cartesian_case):
     init = (1, (2, 3))
     k_size = cartesian_case.default_sizes[KDim]
-    expected = np.arange(1, 1 + k_size, 1, dtype=int64)
+    expected = np.arange(1, 1 + k_size, 1, dtype=int32)
     if not forward:
         expected = np.flip(expected)
 
     @gtx.scan_operator(axis=KDim, forward=forward, init=init)
-    def simple_scan_operator(carry: tuple[int, tuple[int, int]]) -> tuple[int, tuple[int, int]]:
+    def simple_scan_operator(
+        carry: tuple[int32, tuple[int32, int32]]
+    ) -> tuple[int32, tuple[int32, int32]]:
         return (carry[0] + 1, (carry[1][0] + 1, carry[1][1] + 1))
 
     @gtx.program
@@ -687,7 +694,9 @@ def test_domain_input_bounds(cartesian_case):
         return a + a
 
     @gtx.program
-    def program_domain(inp: cases.IField, out: cases.IField, lower_i: int64, upper_i: int64):
+    def program_domain(
+        inp: cases.IField, out: cases.IField, lower_i: gtx.IndexType, upper_i: gtx.IndexType
+    ):
         fieldop_domain(
             inp,
             out=out,
@@ -723,10 +732,10 @@ def test_domain_input_bounds_1(cartesian_case):
     def program_domain(
         a: cases.IJField,
         out: cases.IJField,
-        lower_i: int64,
-        upper_i: int64,
-        lower_j: int64,
-        upper_j: int64,
+        lower_i: gtx.IndexType,
+        upper_i: gtx.IndexType,
+        lower_j: gtx.IndexType,
+        upper_j: gtx.IndexType,
     ):
         fieldop_domain(
             a,
@@ -789,7 +798,21 @@ def test_where_k_offset(cartesian_case):
         pytest.xfail("IndexFields are not supported yet.")
 
     @gtx.field_operator
-    def fieldop_where_k_offset(a: cases.IKField, k_index: cases.KField) -> cases.IKField:
+    def fieldop_where_k_offset(
+        a: cases.IKField, k_index: gtx.Field[[KDim], gtx.IndexType]
+    ) -> cases.IKField:
+        return where(k_index > 0, a(Koff[-1]), 2)
+
+    cases.verify_with_default_data(
+        cartesian_case,
+        fieldop_where_k_offset,
+        ref=lambda a, k_index: np.where(k_index > 0, np.roll(a, 1, axis=1), 2),
+    )
+
+    @gtx.field_operator
+    def fieldop_where_k_offset(
+        a: cases.IKField, k_index: gtx.Field[[KDim], gtx.IndexType]
+    ) -> cases.IKField:
         return where(k_index > 0, a(Koff[-1]), 2)
 
     cases.verify_with_default_data(
@@ -821,7 +844,7 @@ def test_zero_dims_fields(cartesian_case):
 def test_implicit_broadcast_mixed_dim(cartesian_case):
     @gtx.field_operator
     def fieldop_implicit_broadcast(
-        zero_dim_inp: cases.EmptyField, inp: cases.IField, scalar: int
+        zero_dim_inp: cases.EmptyField, inp: cases.IField, scalar: int32
     ) -> cases.IField:
         return inp + zero_dim_inp * scalar
 
@@ -900,7 +923,7 @@ def test_tuple_unpacking_too_many_values(cartesian_case):
     ):
 
         @gtx.field_operator(backend=cartesian_case.backend)
-        def _star_unpack() -> tuple[int, float64, int]:
+        def _star_unpack() -> tuple[int32, float64, int32]:
             a, b, c = (1, 2.0, 3, 4, 5, 6, 7.0)
             return a, b, c
 
@@ -911,7 +934,7 @@ def test_tuple_unpacking_too_many_values(cartesian_case):
     ):
 
         @gtx.field_operator(backend=cartesian_case.backend)
-        def _invalid_unpack() -> tuple[int, float64, int]:
+        def _invalid_unpack() -> tuple[int32, float64, int32]:
             a, b, c = 1
             return a
 
@@ -920,12 +943,12 @@ def test_constant_closure_vars(cartesian_case):
     from gt4py.eve.utils import FrozenNamespace
 
     constants = FrozenNamespace(
-        PI=np.int64(3),
-        E=np.int64(2),
+        PI=np.float64(3.142),
+        E=np.float64(2.718),
     )
 
     @gtx.field_operator
-    def consume_constants(input: cases.IField) -> cases.IField:
+    def consume_constants(input: cases.IFloatField) -> cases.IFloatField:
         return constants.PI * constants.E * input
 
     cases.verify_with_default_data(
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_external_local_field.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_external_local_field.py
index 94382fd7..9c189953 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_external_local_field.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_external_local_field.py
@@ -16,7 +16,7 @@ import numpy as np
 import pytest
 
 import gt4py.next as gtx
-from gt4py.next import int64, neighbor_sum
+from gt4py.next import int32, neighbor_sum
 from gt4py.next.program_processors.runners import gtfn_cpu
 
 from next_tests.integration_tests.feature_tests import cases
@@ -35,7 +35,9 @@ from next_tests.integration_tests.feature_tests.ffront_tests.ffront_test_utils i
 
 def test_external_local_field(unstructured_case):
     @gtx.field_operator
-    def testee(inp: gtx.Field[[Vertex, V2EDim], int64], ones: cases.EField) -> cases.VField:
+    def testee(
+        inp: gtx.Field[[Vertex, V2EDim], int32], ones: gtx.Field[[Edge], int32]
+    ) -> gtx.Field[[Vertex], int32]:
         return neighbor_sum(
             inp * ones(V2E), axis=V2EDim
         )  # multiplication with shifted `ones` because reduction of only non-shifted field with local dimension is not supported
@@ -60,7 +62,7 @@ def test_external_local_field_only(unstructured_case):
         )
 
     @gtx.field_operator
-    def testee(inp: gtx.Field[[Vertex, V2EDim], int64]) -> cases.VField:
+    def testee(inp: gtx.Field[[Vertex, V2EDim], int32]) -> gtx.Field[[Vertex], int32]:
         return neighbor_sum(inp, axis=V2EDim)
 
     inp = gtx.np_as_located_field(Vertex, V2EDim)(unstructured_case.offset_provider["V2E"].table)
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_gt4py_builtins.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_gt4py_builtins.py
index b82e6334..92bd5b99 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_gt4py_builtins.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_gt4py_builtins.py
@@ -17,7 +17,7 @@ import numpy as np
 import pytest
 
 import gt4py.next as gtx
-from gt4py.next import broadcast, float64, int64, max_over, min_over, neighbor_sum, where
+from gt4py.next import broadcast, float64, int32, int64, max_over, min_over, neighbor_sum, where
 from gt4py.next.program_processors.runners import gtfn_cpu
 
 from next_tests.integration_tests.feature_tests import cases
@@ -50,7 +50,9 @@ def test_maxover_execution(unstructured_case):
         pytest.skip("not yet supported.")
 
     @gtx.field_operator
-    def maxover_fieldoperator(inp_field: gtx.Field[[Vertex, V2EDim], int64]) -> cases.VField:
+    def maxover_fieldoperator(
+        inp_field: gtx.Field[[Vertex, V2EDim], int32]
+    ) -> gtx.Field[[Vertex], int32]:
         return max_over(inp_field, axis=V2EDim)
 
     inp = gtx.np_as_located_field(Vertex, V2EDim)(unstructured_case.offset_provider["V2E"].table)
@@ -206,7 +208,7 @@ def test_broadcast_scalar(cartesian_case):
 
 def test_broadcast_two_fields(cartesian_case):
     @gtx.field_operator
-    def broadcast_two_fields(inp1: cases.IField, inp2: gtx.Field[[JDim], int64]) -> cases.IJField:
+    def broadcast_two_fields(inp1: cases.IField, inp2: gtx.Field[[JDim], int32]) -> cases.IJField:
         a = broadcast(inp1, (IDim, JDim))
         b = broadcast(inp2, (IDim, JDim))
         return a + b
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_unary_builtins.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_unary_builtins.py
index af54655a..2f3d9875 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_unary_builtins.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_unary_builtins.py
@@ -25,7 +25,7 @@ from gt4py.next import (
     exp,
     float64,
     floor,
-    int64,
+    int32,
     isfinite,
     isinf,
     isnan,
@@ -90,7 +90,7 @@ def test_mod(cartesian_case):
     def mod_fieldop(inp1: cases.IField) -> cases.IField:
         return inp1 % 2
 
-    inp1 = gtx.np_as_located_field(IDim)(np.asarray(range(10), dtype="int64") - 5)
+    inp1 = gtx.np_as_located_field(IDim)(np.asarray(range(10), dtype=int32) - 5)
     out = cases.allocate(cartesian_case, mod_fieldop, cases.RETURN)()
 
     cases.verify(cartesian_case, mod_fieldop, inp1, out=out, ref=inp1.array() % 2)
diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py
index 4058ef74..b7a44c41 100644
--- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py
+++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_type_deduction.py
@@ -26,6 +26,7 @@ from gt4py.next import (
     broadcast,
     float32,
     float64,
+    int32,
     int64,
     neighbor_sum,
     where,
@@ -481,26 +482,26 @@ def test_remap_nbfield(remap_setup):
 def test_remap_reduce(remap_setup):
     X, Y, Y2XDim, Y2X = remap_setup
 
-    def remap_fo(bar: Field[[X], int64]) -> Field[[Y], int64]:
+    def remap_fo(bar: Field[[X], int32]) -> Field[[Y], int32]:
         return 2 * neighbor_sum(bar(Y2X), axis=Y2XDim)
 
     parsed = FieldOperatorParser.apply_to_function(remap_fo)
 
     assert parsed.body.stmts[0].value.type == ts.FieldType(
-        dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64)
+        dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32)
     )
 
 
 def test_remap_reduce_sparse(remap_setup):
     X, Y, Y2XDim, Y2X = remap_setup
 
-    def remap_fo(bar: Field[[Y, Y2XDim], int64]) -> Field[[Y], int64]:
+    def remap_fo(bar: Field[[Y, Y2XDim], int32]) -> Field[[Y], int32]:
         return 5 * neighbor_sum(bar, axis=Y2XDim)
 
     parsed = FieldOperatorParser.apply_to_function(remap_fo)
 
     assert parsed.body.stmts[0].value.type == ts.FieldType(
-        dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT64)
+        dims=[Y], dtype=ts.ScalarType(kind=ts.ScalarKind.INT32)
     )
 
 
diff --git a/tests/next_tests/unit_tests/ffront_tests/test_foast_to_itir.py b/tests/next_tests/unit_tests/ffront_tests/test_foast_to_itir.py
index 2d565c52..bcc86830 100644
--- a/tests/next_tests/unit_tests/ffront_tests/test_foast_to_itir.py
+++ b/tests/next_tests/unit_tests/ffront_tests/test_foast_to_itir.py
@@ -405,8 +405,8 @@ def test_compare_scalars():
     lowered = FieldOperatorLowering.apply(parsed)
 
     reference = im.promote_to_lifted_stencil("greater")(
-        im.promote_to_const_iterator(im.literal("3", "int64")),
-        im.promote_to_const_iterator(im.literal("4", "int64")),
+        im.promote_to_const_iterator(im.literal("3", "int32")),
+        im.promote_to_const_iterator(im.literal("4", "int32")),
     )
 
     assert lowered.expr == reference
@@ -525,25 +525,21 @@ def test_reduction_lowering_expr():
 def test_builtin_int_constructors():
     def int_constrs() -> (
         tuple[
-            int,
-            int,
+            int32,
             int32,
             int64,
-            int,
             int32,
             int64,
         ]
     ):
-        return 1, int(1), int32(1), int64(1), int("1"), int32("1"), int64("1")
+        return 1, int32(1), int64(1), int32("1"), int64("1")
 
     parsed = FieldOperatorParser.apply_to_function(int_constrs)
     lowered = FieldOperatorLowering.apply(parsed)
 
     reference = im.promote_to_lifted_stencil("make_tuple")(
-        im.promote_to_const_iterator(im.literal("1", "int64")),
-        im.promote_to_const_iterator(im.literal("1", "int64")),
         im.promote_to_const_iterator(im.literal("1", "int32")),
-        im.promote_to_const_iterator(im.literal("1", "int64")),
+        im.promote_to_const_iterator(im.literal("1", "int32")),
         im.promote_to_const_iterator(im.literal("1", "int64")),
         im.promote_to_const_iterator(im.literal("1", "int32")),
         im.promote_to_const_iterator(im.literal("1", "int64")),
diff --git a/tests/next_tests/unit_tests/ffront_tests/test_func_to_foast.py b/tests/next_tests/unit_tests/ffront_tests/test_func_to_foast.py
index c241017b..cb86ef3e 100644
--- a/tests/next_tests/unit_tests/ffront_tests/test_func_to_foast.py
+++ b/tests/next_tests/unit_tests/ffront_tests/test_func_to_foast.py
@@ -179,14 +179,14 @@ def test_binary_pow():
 
 
 def test_binary_mod():
-    def modulo(inp: gtx.Field[[TDim], "int64"]):
+    def modulo(inp: gtx.Field[[TDim], "int32"]):
         return inp % 3
 
     parsed = FieldOperatorParser.apply_to_function(modulo)
 
     assert parsed.body.stmts[-1].value.type == ts.FieldType(
         dims=[TDim],
-        dtype=ts.ScalarType(kind=ts.ScalarKind.INT64, shape=None),
+        dtype=ts.ScalarType(kind=ts.ScalarKind.INT32, shape=None),
     )
 
 
diff --git a/tests/next_tests/unit_tests/ffront_tests/test_past_to_itir.py b/tests/next_tests/unit_tests/ffront_tests/test_past_to_itir.py
index 14b121e7..d6ae5318 100644
--- a/tests/next_tests/unit_tests/ffront_tests/test_past_to_itir.py
+++ b/tests/next_tests/unit_tests/ffront_tests/test_past_to_itir.py
@@ -59,7 +59,7 @@ def test_copy_lowering(copy_program_def, itir_identity_fundef):
                     fun=P(itir.SymRef, id=eve.SymbolRef("named_range")),
                     args=[
                         P(itir.AxisLiteral, value="IDim"),
-                        P(itir.Literal, value="0", type="int"),
+                        P(itir.Literal, value="0", type=itir.INTEGER_INDEX_BUILTIN),
                         P(itir.SymRef, id=eve.SymbolRef("__out_field_size_0")),
                     ],
                 )
@@ -100,8 +100,8 @@ def test_copy_restrict_lowering(copy_restrict_program_def, itir_identity_fundef)
                     fun=P(itir.SymRef, id=eve.SymbolRef("named_range")),
                     args=[
                         P(itir.AxisLiteral, value="IDim"),
-                        P(itir.Literal, value="1", type="int"),
-                        P(itir.Literal, value="2", type="int"),
+                        P(itir.Literal, value="1", type=itir.INTEGER_INDEX_BUILTIN),
+                        P(itir.Literal, value="2", type=itir.INTEGER_INDEX_BUILTIN),
                     ],
                 )
             ],
diff --git a/tests/next_tests/unit_tests/iterator_tests/test_pretty_parser.py b/tests/next_tests/unit_tests/iterator_tests/test_pretty_parser.py
index 75e036c8..e1732d41 100644
--- a/tests/next_tests/unit_tests/iterator_tests/test_pretty_parser.py
+++ b/tests/next_tests/unit_tests/iterator_tests/test_pretty_parser.py
@@ -40,12 +40,15 @@ def test_arithmetic():
                 args=[
                     ir.FunCall(
                         fun=ir.SymRef(id="plus"),
-                        args=[ir.Literal(value="1", type="int"), ir.Literal(value="2", type="int")],
+                        args=[
+                            ir.Literal(value="1", type="int32"),
+                            ir.Literal(value="2", type="int32"),
+                        ],
                     ),
-                    ir.Literal(value="3", type="int"),
+                    ir.Literal(value="3", type="int32"),
                 ],
             ),
-            ir.Literal(value="4", type="int"),
+            ir.Literal(value="4", type="int32"),
         ],
     )
     actual = pparse(testee)
@@ -105,7 +108,8 @@ def test_shift():
 def test_tuple_get():
     testee = "x[42]"
     expected = ir.FunCall(
-        fun=ir.SymRef(id="tuple_get"), args=[ir.Literal(value="42", type="int"), ir.SymRef(id="x")]
+        fun=ir.SymRef(id="tuple_get"),
+        args=[ir.Literal(value="42", type=ir.INTEGER_INDEX_BUILTIN), ir.SymRef(id="x")],
     )
     actual = pparse(testee)
     assert actual == expected
diff --git a/tests/next_tests/unit_tests/iterator_tests/test_pretty_printer.py b/tests/next_tests/unit_tests/iterator_tests/test_pretty_printer.py
index 34626f08..087dee81 100644
--- a/tests/next_tests/unit_tests/iterator_tests/test_pretty_printer.py
+++ b/tests/next_tests/unit_tests/iterator_tests/test_pretty_printer.py
@@ -118,14 +118,14 @@ def test_arithmetic():
                     ir.FunCall(
                         fun=ir.SymRef(id="plus"),
                         args=[
-                            ir.Literal(value="1", type="int"),
-                            ir.Literal(value="2", type="int"),
+                            ir.Literal(value="1", type="int64"),
+                            ir.Literal(value="2", type="int64"),
                         ],
                     ),
-                    ir.Literal(value="3", type="int"),
+                    ir.Literal(value="3", type="int64"),
                 ],
             ),
-            ir.Literal(value="4", type="int"),
+            ir.Literal(value="4", type="int64"),
         ],
     )
     expected = "(1 + 2) × 3 / 4"
@@ -140,15 +140,15 @@ def test_associativity():
             ir.FunCall(
                 fun=ir.SymRef(id="plus"),
                 args=[
-                    ir.Literal(value="1", type="int"),
-                    ir.Literal(value="2", type="int"),
+                    ir.Literal(value="1", type="int64"),
+                    ir.Literal(value="2", type="int64"),
                 ],
             ),
             ir.FunCall(
                 fun=ir.SymRef(id="plus"),
                 args=[
-                    ir.Literal(value="3", type="int"),
-                    ir.Literal(value="4", type="int"),
+                    ir.Literal(value="3", type="int64"),
+                    ir.Literal(value="4", type="int64"),
                 ],
             ),
         ],
@@ -210,7 +210,8 @@ def test_shift():
 
 def test_tuple_get():
     testee = ir.FunCall(
-        fun=ir.SymRef(id="tuple_get"), args=[ir.Literal(value="42", type="int"), ir.SymRef(id="x")]
+        fun=ir.SymRef(id="tuple_get"),
+        args=[ir.Literal(value="42", type=ir.INTEGER_INDEX_BUILTIN), ir.SymRef(id="x")],
     )
     expected = "x[42]"
     actual = pformat(testee)
diff --git a/tests/next_tests/unit_tests/iterator_tests/test_type_inference.py b/tests/next_tests/unit_tests/iterator_tests/test_type_inference.py
index cc39503c..ed9d28a0 100644
--- a/tests/next_tests/unit_tests/iterator_tests/test_type_inference.py
+++ b/tests/next_tests/unit_tests/iterator_tests/test_type_inference.py
@@ -36,19 +36,19 @@ def test_bool_literal():
 
 
 def test_int_literal():
-    testee = ir.Literal(value="3", type="int")
-    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.TypeVar(idx=0))
+    testee = ir.Literal(value="3", type="int32")
+    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.TypeVar(idx=0))
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "int⁰"
+    assert ti.pformat(inferred) == "int32⁰"
 
 
 def test_float_literal():
-    testee = ir.Literal(value="3.0", type="float")
-    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="float"), size=ti.TypeVar(idx=0))
+    testee = ir.Literal(value="3.0", type="float64")
+    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="float64"), size=ti.TypeVar(idx=0))
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "float⁰"
+    assert ti.pformat(inferred) == "float64⁰"
 
 
 def test_deref():
@@ -93,11 +93,11 @@ def test_lambda():
 
 def test_typed_lambda():
     testee = ir.Lambda(
-        params=[ir.Sym(id="x", kind="Iterator", dtype=("float", False))], expr=ir.SymRef(id="x")
+        params=[ir.Sym(id="x", kind="Iterator", dtype=("float64", False))], expr=ir.SymRef(id="x")
     )
     expected_val = ti.Val(
         kind=ti.Iterator(),
-        dtype=ti.Primitive(name="float"),
+        dtype=ti.Primitive(name="float64"),
         size=ti.TypeVar(idx=0),
         current_loc=ti.TypeVar(idx=1),
         defined_loc=ti.TypeVar(idx=2),
@@ -108,7 +108,7 @@ def test_typed_lambda():
     )
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "(It[T₁, T₂, float⁰]) → It[T₁, T₂, float⁰]"
+    assert ti.pformat(inferred) == "(It[T₁, T₂, float64⁰]) → It[T₁, T₂, float64⁰]"
 
 
 def test_plus():
@@ -167,12 +167,13 @@ def test_and():
 
 def test_cast():
     testee = ir.FunCall(
-        fun=ir.SymRef(id="cast_"), args=[ir.Literal(value="1.", type="float"), ir.SymRef(id="int")]
+        fun=ir.SymRef(id="cast_"),
+        args=[ir.Literal(value="1.", type="float64"), ir.SymRef(id="int64")],
     )
-    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.TypeVar(idx=0))
+    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int64"), size=ti.TypeVar(idx=0))
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "int⁰"
+    assert ti.pformat(inferred) == "int64⁰"
 
 
 def test_lift():
@@ -287,40 +288,40 @@ def test_make_tuple():
         fun=ir.SymRef(id="make_tuple"),
         args=[
             ir.Literal(value="True", type="bool"),
-            ir.Literal(value="42.0", type="float"),
+            ir.Literal(value="42.0", type="float64"),
             ir.SymRef(id="x"),
         ],
     )
     expected = ti.Val(
         kind=ti.Value(),
         dtype=ti.Tuple.from_elems(
-            ti.Primitive(name="bool"), ti.Primitive(name="float"), ti.TypeVar(idx=0)
+            ti.Primitive(name="bool"), ti.Primitive(name="float64"), ti.TypeVar(idx=0)
         ),
         size=ti.TypeVar(idx=1),
     )
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "(bool, float, T₀)¹"
+    assert ti.pformat(inferred) == "(bool, float64, T₀)¹"
 
 
 def test_tuple_get():
     testee = ir.FunCall(
         fun=ir.SymRef(id="tuple_get"),
         args=[
-            ir.Literal(value="1", type="int"),
+            ir.Literal(value="1", type=ir.INTEGER_INDEX_BUILTIN),
             ir.FunCall(
                 fun=ir.SymRef(id="make_tuple"),
                 args=[
                     ir.Literal(value="True", type="bool"),
-                    ir.Literal(value="42.0", type="float"),
+                    ir.Literal(value="42.0", type="float64"),
                 ],
             ),
         ],
     )
-    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="float"), size=ti.TypeVar(idx=0))
+    expected = ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="float64"), size=ti.TypeVar(idx=0))
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "float⁰"
+    assert ti.pformat(inferred) == "float64⁰"
 
 
 def test_tuple_get_in_lambda():
@@ -328,7 +329,7 @@ def test_tuple_get_in_lambda():
         params=[ir.Sym(id="x")],
         expr=ir.FunCall(
             fun=ir.SymRef(id="tuple_get"),
-            args=[ir.Literal(value="1", type="int"), ir.SymRef(id="x")],
+            args=[ir.Literal(value="1", type=ir.INTEGER_INDEX_BUILTIN), ir.SymRef(id="x")],
         ),
     )
     expected = ti.FunctionType(
@@ -387,14 +388,14 @@ def test_reduce():
                                 ),
                             ],
                         ),
-                        ir.SymRef(id="int"),
+                        ir.SymRef(id="int64"),
                     ],
                 ),
             ],
         ),
     )
     testee = ir.FunCall(
-        fun=ir.SymRef(id="reduce"), args=[reduction_f, ir.Literal(value="0", type="int")]
+        fun=ir.SymRef(id="reduce"), args=[reduction_f, ir.Literal(value="0", type="int64")]
     )
     expected = ti.FunctionType(
         args=ti.ValListTuple(
@@ -404,11 +405,11 @@ def test_reduce():
             has_skip_values=ti.TypeVar(idx=2),
             size=ti.TypeVar(idx=3),
         ),
-        ret=ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.TypeVar(idx=3)),
+        ret=ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int64"), size=ti.TypeVar(idx=3)),
     )
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "(L[float64, T₁, T₂]³, L[T₀, T₁, T₂]³) → int³"
+    assert ti.pformat(inferred) == "(L[float64, T₁, T₂]³, L[T₀, T₁, T₂]³) → int64³"
 
 
 def test_scan():
@@ -430,30 +431,30 @@ def test_scan():
     )
     testee = ir.FunCall(
         fun=ir.SymRef(id="scan"),
-        args=[scan_f, ir.Literal(value="True", type="bool"), ir.Literal(value="0", type="int")],
+        args=[scan_f, ir.Literal(value="True", type="bool"), ir.Literal(value="0", type="int64")],
     )
     expected = ti.FunctionType(
         args=ti.Tuple.from_elems(
             ti.Val(
                 kind=ti.Iterator(),
-                dtype=ti.Primitive(name="int"),
+                dtype=ti.Primitive(name="int64"),
                 size=ti.Column(),
                 current_loc=ti.TypeVar(idx=0),
                 defined_loc=ti.TypeVar(idx=0),
             ),
             ti.Val(
                 kind=ti.Iterator(),
-                dtype=ti.Primitive(name="int"),
+                dtype=ti.Primitive(name="int64"),
                 size=ti.Column(),
                 current_loc=ti.TypeVar(idx=0),
                 defined_loc=ti.TypeVar(idx=0),
             ),
         ),
-        ret=ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Column()),
+        ret=ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int64"), size=ti.Column()),
     )
     inferred = ti.infer(testee)
     assert inferred == expected
-    assert ti.pformat(inferred) == "(It[T₀, T₀, intᶜ], It[T₀, T₀, intᶜ]) → intᶜ"
+    assert ti.pformat(inferred) == "(It[T₀, T₀, int64ᶜ], It[T₀, T₀, int64ᶜ]) → int64ᶜ"
 
 
 def test_shift():
@@ -646,7 +647,7 @@ CARTESIAN_DOMAIN = ir.FunCall(
             fun=ir.SymRef(id="named_range"),
             args=[
                 ir.AxisLiteral(value="IDim"),
-                ir.Literal(value="0", type="int"),
+                ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                 ir.SymRef(id="i"),
             ],
         ),
@@ -654,7 +655,7 @@ CARTESIAN_DOMAIN = ir.FunCall(
             fun=ir.SymRef(id="named_range"),
             args=[
                 ir.AxisLiteral(value="JDim"),
-                ir.Literal(value="0", type="int"),
+                ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                 ir.SymRef(id="j"),
             ],
         ),
@@ -662,7 +663,7 @@ CARTESIAN_DOMAIN = ir.FunCall(
             fun=ir.SymRef(id="named_range"),
             args=[
                 ir.AxisLiteral(value="KDim"),
-                ir.Literal(value="0", type="int"),
+                ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                 ir.SymRef(id="k"),
             ],
         ),
@@ -732,9 +733,9 @@ def test_fencil_definition():
         name="f",
         fundefs=ti.EmptyTuple(),
         params=ti.Tuple.from_elems(
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
             ti.Val(
                 kind=ti.Iterator(),
                 dtype=ti.TypeVar(idx=0),
@@ -769,7 +770,7 @@ def test_fencil_definition():
     assert inferred == expected
     assert (
         ti.pformat(inferred)
-        == "{f(intˢ, intˢ, intˢ, It[ANYWHERE, T₁, T₀ᶜ], It[ANYWHERE, T₁, T₀ᶜ], It[ANYWHERE, T₃, T₂ᶜ], It[ANYWHERE, T₃, T₂ᶜ])}"
+        == "{f(int32ˢ, int32ˢ, int32ˢ, It[ANYWHERE, T₁, T₀ᶜ], It[ANYWHERE, T₁, T₀ᶜ], It[ANYWHERE, T₃, T₂ᶜ], It[ANYWHERE, T₃, T₂ᶜ])}"
     )
 
 
@@ -788,8 +789,8 @@ def test_fencil_definition_same_closure_input():
                 domain=im.call("unstructured_domain")(
                     im.call("named_range")(
                         ir.AxisLiteral(value="Edge"),
-                        ir.Literal(value="0", type="int"),
-                        ir.Literal(value="10", type="int"),
+                        ir.Literal(value="0", type="int32"),
+                        ir.Literal(value="10", type="int32"),
                     )
                 ),
                 stencil=im.ref("f1"),
@@ -800,8 +801,8 @@ def test_fencil_definition_same_closure_input():
                 domain=im.call("unstructured_domain")(
                     im.call("named_range")(
                         ir.AxisLiteral(value="Vertex"),
-                        ir.Literal(value="0", type="int"),
-                        ir.Literal(value="10", type="int"),
+                        ir.Literal(value="0", type="int32"),
+                        ir.Literal(value="10", type="int32"),
                     )
                 ),
                 stencil=im.ref("f2"),
@@ -917,9 +918,9 @@ def test_fencil_definition_with_function_definitions():
             ),
         ),
         params=ti.Tuple.from_elems(
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
-            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
+            ti.Val(kind=ti.Value(), dtype=ti.Primitive(name="int32"), size=ti.Scalar()),
             ti.Val(
                 kind=ti.Iterator(),
                 dtype=ti.TypeVar(idx=4),
@@ -968,7 +969,7 @@ def test_fencil_definition_with_function_definitions():
     assert inferred == expected
     assert (
         ti.pformat(inferred)
-        == "{f :: (T₀) → T₀, g :: (It[T₃, T₃, T₁²]) → T₁², foo(intˢ, intˢ, intˢ, It[ANYWHERE, T₅, T₄ᶜ], It[ANYWHERE, T₅, T₄ᶜ], It[ANYWHERE, T₇, T₆ᶜ], It[ANYWHERE, T₇, T₆ᶜ], It[ANYWHERE, T₉, T₈ᶜ], It[ANYWHERE, T₉, T₈ᶜ])}"
+        == "{f :: (T₀) → T₀, g :: (It[T₃, T₃, T₁²]) → T₁², foo(int32ˢ, int32ˢ, int32ˢ, It[ANYWHERE, T₅, T₄ᶜ], It[ANYWHERE, T₅, T₄ᶜ], It[ANYWHERE, T₇, T₆ᶜ], It[ANYWHERE, T₇, T₆ᶜ], It[ANYWHERE, T₉, T₈ᶜ], It[ANYWHERE, T₉, T₈ᶜ])}"
     )
 
 
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collapse_list_get.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collapse_list_get.py
index 448a5ad6..b025b761 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collapse_list_get.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collapse_list_get.py
@@ -26,7 +26,7 @@ def _neighbors(offset: ir.Expr, it: ir.Expr) -> ir.FunCall:
 
 def test_list_get_neighbors():
     testee = _list_get(
-        ir.Literal(value="42", type="int"),
+        ir.Literal(value="42", type="int32"),
         _neighbors(ir.OffsetLiteral(value="foo"), ir.SymRef(id="bar")),
     )
 
@@ -52,7 +52,7 @@ def test_list_get_neighbors():
 
 def test_list_get_make_const_list():
     testee = _list_get(
-        ir.Literal(value="42", type="int"),
+        ir.Literal(value="42", type="int32"),
         ir.FunCall(
             fun=ir.SymRef(id="make_const_list"), args=[ir.Literal(value="3.14", type="float64")]
         ),
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collect_shifts.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collect_shifts.py
index 0f0a3f78..20a784cf 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collect_shifts.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_collect_shifts.py
@@ -40,7 +40,7 @@ def test_reduce():
     testee = ir.FunCall(
         fun=ir.FunCall(
             fun=ir.SymRef(id="reduce"),
-            args=[ir.SymRef(id="plus"), ir.Literal(value="0.0", type="float")],
+            args=[ir.SymRef(id="plus"), ir.Literal(value="0.0", type="float64")],
         ),
         args=[
             ir.FunCall(
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_cse.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_cse.py
index 2349fb8a..3ce17bc8 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_cse.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_cse.py
@@ -143,14 +143,14 @@ def test_if_can_deref_no_extraction():
         im.call("can_deref")(im.shift("I", 1)("it")),
         im.plus(im.deref(im.shift("I", 1)("it")), im.deref(im.shift("I", 1)("it"))),
         # use something more involved where a subexpression can still be eliminated
-        im.literal("1", "int"),
+        im.literal("1", "int32"),
     )
     # (λ(_cs_1) → if can_deref(_cs_1) then (λ(_cs_2) → _cs_2 + _cs_2)(·_cs_1) else 1)(⟪Iₒ, 1ₒ⟫(it))
     expected = im.let("_cs_1", im.shift("I", 1)("it"))(
         im.if_(
             im.call("can_deref")("_cs_1"),
             im.let("_cs_2", im.deref("_cs_1"))(im.plus("_cs_2", "_cs_2")),
-            im.literal("1", "int"),
+            im.literal("1", "int32"),
         )
     )
 
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_global_tmps.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_global_tmps.py
index bd72635b..a01c33c5 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_global_tmps.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_global_tmps.py
@@ -183,7 +183,7 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value=a),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.SymRef(id=s),
                                 ],
                             )
@@ -247,10 +247,13 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value="IDim"),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.FunCall(
                                         fun=ir.SymRef(id="plus"),
-                                        args=[ir.SymRef(id="i"), ir.Literal(value="1", type="int")],
+                                        args=[
+                                            ir.SymRef(id="i"),
+                                            ir.Literal(value="1", type=ir.INTEGER_INDEX_BUILTIN),
+                                        ],
                                     ),
                                 ],
                             )
@@ -260,7 +263,7 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value=a),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.SymRef(id=s),
                                 ],
                             )
@@ -285,10 +288,13 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value="IDim"),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.FunCall(
                                         fun=ir.SymRef(id="plus"),
-                                        args=[ir.SymRef(id="i"), ir.Literal(value="1", type="int")],
+                                        args=[
+                                            ir.SymRef(id="i"),
+                                            ir.Literal(value="1", type=ir.INTEGER_INDEX_BUILTIN),
+                                        ],
                                     ),
                                 ],
                             )
@@ -298,7 +304,7 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value=a),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.SymRef(id=s),
                                 ],
                             )
@@ -317,7 +323,7 @@ def test_update_cartesian_domains():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value=a),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.SymRef(id=s),
                                 ],
                             )
@@ -371,10 +377,13 @@ def test_collect_tmps_info():
                 fun=ir.SymRef(id="named_range"),
                 args=[
                     ir.AxisLiteral(value="IDim"),
-                    ir.Literal(value="0", type="int"),
+                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                     ir.FunCall(
                         fun=ir.SymRef(id="plus"),
-                        args=[ir.SymRef(id="i"), ir.Literal(value="1", type="int")],
+                        args=[
+                            ir.SymRef(id="i"),
+                            ir.Literal(value="1", type=ir.INTEGER_INDEX_BUILTIN),
+                        ],
                     ),
                 ],
             )
@@ -384,7 +393,7 @@ def test_collect_tmps_info():
                 fun=ir.SymRef(id="named_range"),
                 args=[
                     ir.AxisLiteral(value=a),
-                    ir.Literal(value="0", type="int"),
+                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                     ir.SymRef(id=s),
                 ],
             )
@@ -431,7 +440,7 @@ def test_collect_tmps_info():
                                 fun=ir.SymRef(id="named_range"),
                                 args=[
                                     ir.AxisLiteral(value=a),
-                                    ir.Literal(value="0", type="int"),
+                                    ir.Literal(value="0", type=ir.INTEGER_INDEX_BUILTIN),
                                     ir.SymRef(id=s),
                                 ],
                             )
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_inline_into_scan.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_inline_into_scan.py
index b85cf694..50a3b3ec 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_inline_into_scan.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_inline_into_scan.py
@@ -25,7 +25,7 @@ def _make_scan(*args: list[str], scanpass_body: ir.Expr) -> ir.Expr:
                 params=[ir.Sym(id="state")] + [ir.Sym(id=f"{arg}") for arg in args],
                 expr=scanpass_body,
             ),
-            ir.Literal(value="0.0", type="float"),
+            ir.Literal(value="0.0", type="float64"),
             ir.Literal(value="True", type="bool"),
         ],
     )
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_scan_eta_reduction.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_scan_eta_reduction.py
index 8ba105e1..e86fb658 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_scan_eta_reduction.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_scan_eta_reduction.py
@@ -24,7 +24,7 @@ def _make_scan(*args: list[str]):
                 params=[ir.Sym(id="state")] + [ir.Sym(id=f"{arg}") for arg in args],
                 expr=ir.SymRef(id="foo"),
             ),
-            ir.Literal(value="0.0", type="float"),
+            ir.Literal(value="0.0", type="float64"),
             ir.Literal(value="True", type="bool"),
         ],
     )
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_simple_inline_heuristic.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_simple_inline_heuristic.py
index 8e614900..a236d793 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_simple_inline_heuristic.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_simple_inline_heuristic.py
@@ -34,7 +34,7 @@ def scan():
                 ),
             ),
             ir.Literal(value="True", type="bool"),
-            ir.Literal(value="0.0", type="float"),
+            ir.Literal(value="0.0", type="float64"),
         ],
     )
 
diff --git a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_unroll_reduce.py b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_unroll_reduce.py
index 8be6f797..9f1462dd 100644
--- a/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_unroll_reduce.py
+++ b/tests/next_tests/unit_tests/iterator_tests/transforms_tests/test_unroll_reduce.py
@@ -34,7 +34,7 @@ def basic_reduction():
     return ir.FunCall(
         fun=ir.FunCall(
             fun=ir.SymRef(id="reduce"),
-            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float")],
+            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float64")],
         ),
         args=[
             ir.FunCall(
@@ -51,7 +51,7 @@ def reduction_with_shift_on_second_arg():
     return ir.FunCall(
         fun=ir.FunCall(
             fun=ir.SymRef(id="reduce"),
-            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float")],
+            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float64")],
         ),
         args=[
             ir.SymRef(id="x"),
@@ -69,7 +69,7 @@ def reduction_with_incompatible_shifts():
     return ir.FunCall(
         fun=ir.FunCall(
             fun=ir.SymRef(id="reduce"),
-            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float")],
+            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float64")],
         ),
         args=[
             ir.FunCall(
@@ -90,7 +90,7 @@ def reduction_with_irrelevant_full_shift():
     return ir.FunCall(
         fun=ir.FunCall(
             fun=ir.SymRef(id="reduce"),
-            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float")],
+            args=[ir.SymRef(id="foo"), ir.Literal(value="0.0", type="float64")],
         ),
         args=[
             ir.FunCall(
diff --git a/tests/next_tests/unit_tests/program_processor_tests/codegens_tests/gtfn_tests/test_gtfn_module.py b/tests/next_tests/unit_tests/program_processor_tests/codegens_tests/gtfn_tests/test_gtfn_module.py
index 5e69db01..93be8846 100644
--- a/tests/next_tests/unit_tests/program_processor_tests/codegens_tests/gtfn_tests/test_gtfn_module.py
+++ b/tests/next_tests/unit_tests/program_processor_tests/codegens_tests/gtfn_tests/test_gtfn_module.py
@@ -30,8 +30,8 @@ def fencil_example():
                 fun=itir.SymRef(id="named_range"),
                 args=[
                     itir.AxisLiteral(value="X"),
-                    itir.Literal(value="0", type="int"),
-                    itir.Literal(value="10", type="int"),
+                    itir.Literal(value="0", type=itir.INTEGER_INDEX_BUILTIN),
+                    itir.Literal(value="10", type=itir.INTEGER_INDEX_BUILTIN),
                 ],
             )
         ],
@@ -43,7 +43,7 @@ def fencil_example():
             itir.FunctionDefinition(
                 id="stencil",
                 params=[itir.Sym(id="buf"), itir.Sym(id="sc")],
-                expr=itir.Literal(value="1", type="float"),
+                expr=itir.Literal(value="1", type="float64"),
             )
         ],
         closures=[
diff --git a/tests/next_tests/unit_tests/type_system_tests/test_type_translation.py b/tests/next_tests/unit_tests/type_system_tests/test_type_translation.py
index 4a184072..ab3ef80b 100644
--- a/tests/next_tests/unit_tests/type_system_tests/test_type_translation.py
+++ b/tests/next_tests/unit_tests/type_system_tests/test_type_translation.py
@@ -65,7 +65,7 @@ def test_invalid_scalar_kind():
             typing.Tuple[int, float],
             ts.TupleType(
                 types=[
-                    ts.ScalarType(kind=ts.ScalarKind.INT),
+                    ts.ScalarType(kind=ts.ScalarKind.INT64),
                     ts.ScalarType(kind=ts.ScalarKind.FLOAT64),
                 ]
             ),
@@ -77,7 +77,7 @@ def test_invalid_scalar_kind():
                     ts.ScalarType(kind=ts.ScalarKind.BOOL),
                     ts.TupleType(
                         types=[
-                            ts.ScalarType(kind=ts.ScalarKind.INT),
+                            ts.ScalarType(kind=ts.ScalarKind.INT64),
                             ts.ScalarType(kind=ts.ScalarKind.FLOAT64),
                         ]
                     ),
@@ -102,10 +102,10 @@ def test_invalid_scalar_kind():
             ts.FunctionType(
                 args=[
                     ts.ScalarType(kind=ts.ScalarKind.FLOAT64),
-                    ts.ScalarType(kind=ts.ScalarKind.INT),
+                    ts.ScalarType(kind=ts.ScalarKind.INT64),
                 ],
                 kwargs={},
-                returns=ts.ScalarType(kind=ts.ScalarKind.INT),
+                returns=ts.ScalarType(kind=ts.ScalarKind.INT64),
             ),
         ),
         (typing.ForwardRef("float"), ts.ScalarType(kind=ts.ScalarKind.FLOAT64)),