Repository: carbon-language/carbon-lang (2026-06-11T10:12:27Z)

Issue:
crash after diagnostic when attempting to use an overly-large integer type
### Description of the bug:


Carbon limits integer types to bit widths up to 2^23 (inclusive). Attempting to go beyond that limit produces a diagnostic followed by a CHECK failure.

### What did you do, or what's a simple way to reproduce the bug?


```carbon
let ok: i8388608 = 0;

// Diagnoses not a multiple of 8 then crashes.
let bad1: i8388609 = 0;

// Diagnoses too large then crashes.
let bad2: Core.Int(8388609) = 0;

// Diagnoses too large then crashes.
let bad3: i16777216 = 0;
```

[Live example](https://carbon.godbolt.org/z/Wro64ocds)

### What did you expect to happen?


Diagnostic that the integer type is too large.

### What actually happened?


CHECK failure.

### Any other information, logs, or outputs that you want to share?


_No response_


Discussion:

Patch:
diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp
index 0c6e33c30d260..f218330f894ea 100644
--- a/toolchain/check/eval.cpp
+++ b/toolchain/check/eval.cpp
@@ -1327,8 +1327,14 @@ static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
                               SemIR::TypeId dest_type_id) -> SemIR::ConstantId {
   auto arg_val =
       context.ints().Get(context.insts().GetAs<SemIR::IntValue>(arg_id).int_id);
-  auto [dest_is_signed, bit_width_id] =
-      context.sem_ir().types().GetIntTypeInfo(dest_type_id);
+  auto dest_int_info = context.sem_ir().types().TryGetIntTypeInfo(dest_type_id);
+  if (!dest_int_info) {
+    // The destination is not a valid integer type, such as when its bit width
+    // was diagnosed as invalid. The error was already diagnosed when forming
+    // the type, so just produce an error value.
+    return SemIR::ErrorInst::ConstantId;
+  }
+  auto [dest_is_signed, bit_width_id] = *dest_int_info;
   if (bit_width_id.has_value()) {
     // TODO: If the value fits in the destination type, reuse the existing
     // int_id rather than recomputing it. This is probably the most common case.
@@ -1351,8 +1357,12 @@ static auto PerformCheckedIntConvert(Context& context, SemIR::LocId loc_id,
   auto arg = context.insts().GetAs<SemIR::IntValue>(arg_id);
   auto arg_val = context.ints().Get(arg.int_id);
 
-  auto [is_signed, bit_width_id] =
-      context.sem_ir().types().GetIntTypeInfo(dest_type_id);
+  auto dest_int_info = context.sem_ir().types().TryGetIntTypeInfo(dest_type_id);
+  if (!dest_int_info) {
+    // The destination is not a valid integer type; see PerformIntConvert.
+    return SemIR::ErrorInst::ConstantId;
+  }
+  auto [is_signed, bit_width_id] = *dest_int_info;
   auto width = bit_width_id.has_value()
                    ? context.ints().Get(bit_width_id).getZExtValue()
                    : arg_val.getBitWidth();


Test patch:
diff --git a/toolchain/check/testdata/builtins/int/fail_convert_oversized_type.carbon b/toolchain/check/testdata/builtins/int/fail_convert_oversized_type.carbon
new file mode 100644
index 0000000000000..4023ab21c8782
--- /dev/null
+++ b/toolchain/check/testdata/builtins/int/fail_convert_oversized_type.carbon
@@ -0,0 +1,57 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/fail_convert_oversized_type.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/fail_convert_oversized_type.carbon
+
+// --- fail_width_not_multiple_of_8.carbon
+
+library "[[@TEST_NAME]]";
+
+// Initializing a binding whose type is an invalid integer type must not crash
+// constant evaluation (#7278). The type is diagnosed; the conversion of the
+// initializer should then produce an error value, not a CHECK failure.
+// CHECK:STDERR: fail_width_not_multiple_of_8.carbon:[[@LINE+11]]:10: error: bit width of integer type literal must be a multiple of 8; use `Core.Int(8388609)` instead [IntWidthNotMultipleOf8]
+// CHECK:STDERR: let bad: i8388609 = 0;
+// CHECK:STDERR:          ^~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_width_not_multiple_of_8.carbon:[[@LINE+7]]:10: error: binding pattern has incomplete type `i8388609` in name binding declaration [IncompleteTypeInBindingDecl]
+// CHECK:STDERR: let bad: i8388609 = 0;
+// CHECK:STDERR:          ^~~~~~~~
+// CHECK:STDERR: {{.*}}/prelude/types/int.carbon:18:9: note: integer type width of 8388609 is greater than the maximum supported width of 8388608 [IntWidthTooLarge]
+// CHECK:STDERR:   adapt MakeInt(N);
+// CHECK:STDERR:         ^~~~~~~~~~
+// CHECK:STDERR:
+let bad: i8388609 = 0;
+
+// --- fail_width_too_large.carbon
+
+library "[[@TEST_NAME]]";
+
+// CHECK:STDERR: fail_width_too_large.carbon:[[@LINE+7]]:10: error: binding pattern has incomplete type `i16777216` in name binding declaration [IncompleteTypeInBindingDecl]
+// CHECK:STDERR: let bad: i16777216 = 0;
+// CHECK:STDERR:          ^~~~~~~~~
+// CHECK:STDERR: {{.*}}/prelude/types/int.carbon:18:9: note: integer type width of 16777216 is greater than the maximum supported width of 8388608 [IntWidthTooLarge]
+// CHECK:STDERR:   adapt MakeInt(N);
+// CHECK:STDERR:         ^~~~~~~~~~
+// CHECK:STDERR:
+let bad: i16777216 = 0;
+
+// --- fail_width_too_large_core_int.carbon
+
+library "[[@TEST_NAME]]";
+
+// CHECK:STDERR: fail_width_too_large_core_int.carbon:[[@LINE+7]]:10: error: binding pattern has incomplete type `i8388609` in name binding declaration [IncompleteTypeInBindingDecl]
+// CHECK:STDERR: let bad: Core.Int(8388609) = 0;
+// CHECK:STDERR:          ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR: {{.*}}/prelude/types/int.carbon:18:9: note: integer type width of 8388609 is greater than the maximum supported width of 8388608 [IntWidthTooLarge]
+// CHECK:STDERR:   adapt MakeInt(N);
+// CHECK:STDERR:         ^~~~~~~~~~
+// CHECK:STDERR:
+let bad: Core.Int(8388609) = 0;