Ver código fonte

Id::Invalid -> Id::None (#4834)

High level, replacing `Id::Invalid` with `Id::None` and `Id::is_valid`
with `Id::has_value` for clarity, as discussed
[here](https://discord.com/channels/655572317891461132/655578254970716160/1331664574545395794).
The `IntId` refactoring is needed together with `AnyIdBase` because it's
also used with `ValueStore`.

Note, trying to be careful not to rewrite `EnumBase::InvalidIndex`, or
`is_valid` in general (e.g., `IdKind::is_valid`).

I've tried to sequence commits here:

1. Automatic replacements:

- `((?:Id|Index)(?: |::|\(|Base(?:\(|::)))Invalid((?:Index)?\W)` ->
`$1None$2`
  - `<invalid>` -> `<none>`
  - `InvalidNodeId` -> `NoneNodeId`
  - `/\*invalid\*/` -> `/*none*/`
  - `id((?:_|\(\))(?:\.|->))is_valid` -> `id$1has_value`

2. Manual edits:

  - In `int.h` and `int_test.cpp`
    - `IntT` has `is_value`, which I'm renaming to `is_embedded_value`.
    - Manual edits to comments in this file.
  - `AnyIdBase` and `IdBase`
- Declaration of `is_valid` -> `has_value`, `InvalidIndex` ->
`NoneIndex`.
  - In `ids.h` and `ids.cpp`
    - `is_valid` -> `has_value`
- `// An explicitly invalid ID.` -> `// An ID with no value.`; similar
for index
    - Various math on `InvalidIndex` -> `NoneIndex`
    - Various mentions of "valid" in comments
  - In `value_store.h`, for `IdT::Invalid`, plus one comment
- In `impl.h` and `tokenized_buffer.h`, we had different initialization
of `::None` values (versus `ids.h` syntax) that I fixed manually.
  - Spot checks to compile
- Particularly where `is_valid` replacements didn't catch spots due to
different naming.

3. Autoupdate tests

4. verbose.carbon (NOAUTOUPDATE)

5. Comment spot checks

Note there are probably other mentions of "Invalid" that should be swept
up, but I'd like to argue for merging and separating out remaining
cleanup since this is so sweeping (and likely to hit merge conflicts
from churn). We'll probably have lingering mentions of "invalid" for a
bit regardless, just because there are uses of "invalid" in non-Id APIs.
Jon Ross-Perkins 1 ano atrás
pai
commit
6b5eb1a101
100 arquivos alterados com 880 adições e 884 exclusões
  1. 4 4
      toolchain/base/index_base.h
  2. 5 5
      toolchain/base/int.cpp
  3. 49 49
      toolchain/base/int.h
  4. 7 7
      toolchain/base/int_test.cpp
  5. 10 10
      toolchain/base/value_ids.h
  6. 2 2
      toolchain/base/value_store.h
  7. 10 10
      toolchain/base/value_store_test.cpp
  8. 10 10
      toolchain/check/call.cpp
  9. 14 14
      toolchain/check/check.cpp
  10. 15 15
      toolchain/check/check_unit.cpp
  11. 1 1
      toolchain/check/check_unit.h
  12. 42 43
      toolchain/check/context.cpp
  13. 8 8
      toolchain/check/context.h
  14. 21 21
      toolchain/check/convert.cpp
  15. 1 1
      toolchain/check/convert.h
  16. 3 4
      toolchain/check/decl_introducer_state.h
  17. 16 16
      toolchain/check/decl_name_stack.cpp
  18. 6 6
      toolchain/check/decl_name_stack.h
  19. 19 20
      toolchain/check/deduce.cpp
  20. 1 1
      toolchain/check/deduce.h
  21. 1 1
      toolchain/check/dump.cpp
  22. 50 49
      toolchain/check/eval.cpp
  23. 2 2
      toolchain/check/function.cpp
  24. 1 1
      toolchain/check/function.h
  25. 16 16
      toolchain/check/generic.cpp
  26. 4 3
      toolchain/check/generic.h
  27. 9 9
      toolchain/check/global_init.cpp
  28. 3 3
      toolchain/check/handle_alias.cpp
  29. 15 16
      toolchain/check/handle_binding_pattern.cpp
  30. 25 25
      toolchain/check/handle_class.cpp
  31. 1 1
      toolchain/check/handle_export.cpp
  32. 19 19
      toolchain/check/handle_function.cpp
  33. 19 19
      toolchain/check/handle_impl.cpp
  34. 11 12
      toolchain/check/handle_interface.cpp
  35. 4 4
      toolchain/check/handle_let_and_var.cpp
  36. 4 4
      toolchain/check/handle_modifier.cpp
  37. 4 4
      toolchain/check/handle_name.cpp
  38. 5 5
      toolchain/check/handle_namespace.cpp
  39. 1 1
      toolchain/check/handle_struct.cpp
  40. 3 3
      toolchain/check/handle_where.cpp
  41. 20 20
      toolchain/check/impl.cpp
  42. 12 12
      toolchain/check/impl_lookup.cpp
  43. 1 1
      toolchain/check/impl_lookup.h
  44. 15 14
      toolchain/check/import.cpp
  45. 146 148
      toolchain/check/import_ref.cpp
  46. 3 3
      toolchain/check/inst_block_stack.cpp
  47. 1 1
      toolchain/check/inst_block_stack.h
  48. 12 12
      toolchain/check/member_access.cpp
  49. 17 17
      toolchain/check/merge.cpp
  50. 1 1
      toolchain/check/merge.h
  51. 5 5
      toolchain/check/modifiers.cpp
  52. 12 11
      toolchain/check/name_component.cpp
  53. 1 1
      toolchain/check/name_component.h
  54. 4 5
      toolchain/check/node_id_traversal.cpp
  55. 2 2
      toolchain/check/node_id_traversal.h
  56. 5 5
      toolchain/check/node_stack.h
  57. 25 25
      toolchain/check/pattern_match.cpp
  58. 9 9
      toolchain/check/return.cpp
  59. 2 2
      toolchain/check/scope_index.h
  60. 16 16
      toolchain/check/scope_stack.cpp
  61. 7 7
      toolchain/check/scope_stack.h
  62. 13 13
      toolchain/check/sem_ir_diagnostic_converter.cpp
  63. 1 1
      toolchain/check/sem_ir_diagnostic_converter.h
  64. 9 9
      toolchain/check/subst.cpp
  65. 5 5
      toolchain/check/testdata/alias/no_prelude/export_name.carbon
  66. 1 1
      toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon
  67. 1 1
      toolchain/check/testdata/alias/no_prelude/fail_name_conflict.carbon
  68. 1 1
      toolchain/check/testdata/alias/no_prelude/fail_params.carbon
  69. 4 4
      toolchain/check/testdata/alias/no_prelude/import.carbon
  70. 2 2
      toolchain/check/testdata/alias/no_prelude/import_access.carbon
  71. 2 2
      toolchain/check/testdata/alias/no_prelude/import_order.carbon
  72. 1 1
      toolchain/check/testdata/alias/no_prelude/in_namespace.carbon
  73. 2 2
      toolchain/check/testdata/array/generic_empty.carbon
  74. 1 1
      toolchain/check/testdata/array/import.carbon
  75. 2 2
      toolchain/check/testdata/array/init_dependent_bound.carbon
  76. 7 7
      toolchain/check/testdata/as/adapter_conversion.carbon
  77. 1 1
      toolchain/check/testdata/as/overloaded.carbon
  78. 3 3
      toolchain/check/testdata/basics/builtin_insts.carbon
  79. 1 1
      toolchain/check/testdata/basics/no_prelude/verbose.carbon
  80. 4 4
      toolchain/check/testdata/builtins/bool/eq.carbon
  81. 1 1
      toolchain/check/testdata/builtins/bool/make_type.carbon
  82. 4 4
      toolchain/check/testdata/builtins/bool/neq.carbon
  83. 2 2
      toolchain/check/testdata/builtins/float/make_type.carbon
  84. 3 3
      toolchain/check/testdata/class/access_modifers.carbon
  85. 2 2
      toolchain/check/testdata/class/adapter/adapt.carbon
  86. 4 4
      toolchain/check/testdata/class/adapter/extend_adapt.carbon
  87. 12 12
      toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon
  88. 4 4
      toolchain/check/testdata/class/adapter/init_adapt.carbon
  89. 3 3
      toolchain/check/testdata/class/base.carbon
  90. 5 5
      toolchain/check/testdata/class/base_field.carbon
  91. 1 1
      toolchain/check/testdata/class/base_method.carbon
  92. 1 1
      toolchain/check/testdata/class/basic.carbon
  93. 1 1
      toolchain/check/testdata/class/complete_in_member_fn.carbon
  94. 5 5
      toolchain/check/testdata/class/compound_field.carbon
  95. 3 3
      toolchain/check/testdata/class/derived_to_base.carbon
  96. 5 5
      toolchain/check/testdata/class/fail_abstract.carbon
  97. 2 2
      toolchain/check/testdata/class/fail_addr_not_self.carbon
  98. 1 1
      toolchain/check/testdata/class/fail_base_bad_type.carbon
  99. 2 2
      toolchain/check/testdata/class/fail_compound_type_mismatch.carbon
  100. 1 1
      toolchain/check/testdata/class/fail_convert_to_invalid.carbon

+ 4 - 4
toolchain/base/index_base.h

@@ -20,12 +20,12 @@ class DataIterator;
 
 // Non-templated portions of `IdBase`.
 struct AnyIdBase {
-  static constexpr int32_t InvalidIndex = -1;
+  static constexpr int32_t NoneIndex = -1;
 
   AnyIdBase() = delete;
   constexpr explicit AnyIdBase(int index) : index(index) {}
 
-  constexpr auto is_valid() const -> bool { return index != InvalidIndex; }
+  constexpr auto has_value() const -> bool { return index != NoneIndex; }
 
   int32_t index;
 };
@@ -50,10 +50,10 @@ struct IdBase : public AnyIdBase, public Printable<IdT> {
 
   auto Print(llvm::raw_ostream& out) const -> void {
     out << IdT::Label;
-    if (is_valid()) {
+    if (has_value()) {
       out << index;
     } else {
-      out << "<invalid>";
+      out << "<none>";
     }
   }
 

+ 5 - 5
toolchain/base/int.cpp

@@ -30,28 +30,28 @@ auto IntStore::CanonicalizeUnsigned(llvm::APInt value) -> llvm::APInt {
 auto IntStore::AddLarge(int64_t value) -> IntId {
   auto ap_id =
       values_.Add(llvm::APInt(CanonicalBitWidth(64), value, /*isSigned=*/true));
-  return MakeIndexOrInvalid(ap_id.index);
+  return MakeIndexOrNone(ap_id.index);
 }
 
 auto IntStore::AddSignedLarge(llvm::APInt value) -> IntId {
   auto ap_id = values_.Add(CanonicalizeSigned(value));
-  return MakeIndexOrInvalid(ap_id.index);
+  return MakeIndexOrNone(ap_id.index);
 }
 
 auto IntStore::AddUnsignedLarge(llvm::APInt value) -> IntId {
   auto ap_id = values_.Add(CanonicalizeUnsigned(value));
-  return MakeIndexOrInvalid(ap_id.index);
+  return MakeIndexOrNone(ap_id.index);
 }
 
 auto IntStore::LookupLarge(int64_t value) const -> IntId {
   auto ap_id = values_.Lookup(
       llvm::APInt(CanonicalBitWidth(64), value, /*isSigned=*/true));
-  return MakeIndexOrInvalid(ap_id.index);
+  return MakeIndexOrNone(ap_id.index);
 }
 
 auto IntStore::LookupSignedLarge(llvm::APInt value) const -> IntId {
   auto ap_id = values_.Lookup(CanonicalizeSigned(value));
-  return MakeIndexOrInvalid(ap_id.index);
+  return MakeIndexOrNone(ap_id.index);
 }
 
 auto IntStore::OutputYaml() const -> Yaml::OutputMapping {

+ 49 - 49
toolchain/base/int.h

@@ -47,9 +47,9 @@ struct IntStoreTestPeer;
 // to the 32-bit signed integer minimum, supporting approximately 1.998 billion
 // unique larger integers.
 //
-// Note that the invalid ID can't be used with a token. This is OK as we
-// expect invalid tokens to be *error* tokens and not need to represent an
-// invalid integer.
+// Note the `None` ID can't be used with a token. This is OK as we expect
+// invalid tokens to be *error* tokens and not need to represent an invalid
+// integer.
 class IntId : public Printable<IntId> {
  public:
   static constexpr llvm::StringLiteral Label = "int";
@@ -65,7 +65,7 @@ class IntId : public Printable<IntId> {
   // tokens or computed after lexing outside of this range.
   static constexpr int TokenIdBits = 23;
 
-  static const IntId Invalid;
+  static const IntId None;
 
   static auto MakeFromTokenPayload(uint32_t payload) -> IntId {
     // Token-associated IDs are signed `TokenIdBits` integers, so force sign
@@ -79,33 +79,34 @@ class IntId : public Printable<IntId> {
     return IntId(raw_id);
   }
 
-  // Tests whether the ID is a value ID.
+  // Tests whether the ID is an embedded value ID.
   //
-  // Only *valid* IDs can have an embedded value, so when true this also implies
-  // the ID is valid.
-  constexpr auto is_value() const -> bool { return id_ > ZeroIndexId; }
+  // Note `None` is not an embedded value, so this implies `has_value()` is
+  // true.
+  constexpr auto is_embedded_value() const -> bool { return id_ > ZeroIndexId; }
 
   // Tests whether the ID is an index ID.
   //
-  // Note that an invalid ID is represented as an index ID, so this is *not*
-  // sufficient to test whether an ID is valid.
+  // Note `None` is represented as an index ID, so this is *not* sufficient to
+  // test `has_value()`.
   constexpr auto is_index() const -> bool { return id_ <= ZeroIndexId; }
 
-  // Test whether an ID is valid.
+  // Test whether a value is present.
   //
-  // This does not distinguish between value and index IDs, only whether valid.
-  constexpr auto is_valid() const -> bool { return id_ != InvalidId; }
+  // This does not distinguish between embedded values and index IDs, only
+  // whether some value is present.
+  constexpr auto has_value() const -> bool { return id_ != NoneId; }
 
-  // Converts an ID to the embedded value. Requires that `is_value()` is true.
+  // Converts an ID to the embedded value. Requires that `is_embedded_value()`
+  // is true.
   constexpr auto AsValue() const -> int {
-    CARBON_DCHECK(is_value());
+    CARBON_DCHECK(is_embedded_value());
     return id_;
   }
 
   // Converts an ID to an index. Requires that `is_index()` is true.
   //
-  // Note that this does *not* require that the ID is valid. An invalid ID will
-  // turn into an invalid index.
+  // Note `None` is represented as an index ID, and can be converted here.
   constexpr auto AsIndex() const -> int {
     CARBON_DCHECK(is_index());
     return ZeroIndexId - id_;
@@ -123,13 +124,13 @@ class IntId : public Printable<IntId> {
 
   auto Print(llvm::raw_ostream& out) const -> void {
     out << Label << "(";
-    if (is_value()) {
+    if (is_embedded_value()) {
       out << "value: " << AsValue();
     } else if (is_index()) {
       out << "index: " << AsIndex();
     } else {
-      CARBON_CHECK(!is_valid());
-      out << "<invalid>";
+      CARBON_CHECK(!has_value());
+      out << "<none>";
     }
     out << ")";
   }
@@ -173,17 +174,17 @@ class IntId : public Printable<IntId> {
   // The minimum embedded value in an ID.
   static constexpr int32_t MinValue = ZeroIndexId + 1;
 
-  // The invalid ID, which needs to be placed after the largest index, which
+  // The `None` ID, which needs to be placed after the largest index, which
   // count downwards as IDs so below the smallest index ID, in order to optimize
   // the code sequence needed to distinguish between integer and value IDs and
   // to convert index IDs into actual indices small.
-  static constexpr int32_t InvalidId = std::numeric_limits<int32_t>::min();
+  static constexpr int32_t NoneId = std::numeric_limits<int32_t>::min();
 
-  // The invalid index. This is the result of converting an invalid ID into an
+  // The `None` index. This is the result of converting a `None` ID into an
   // index. We ensure that conversion can be done so that we can simplify the
   // code that first tries to use an embedded value, then converts to an index
-  // and checks that the index is valid.
-  static const int32_t InvalidIndex;
+  // and checks that the index is still `None`.
+  static const int32_t NoneIndex;
 
   // Document the specific values of some of these constants to help visualize
   // how the bit patterns map from the above computations.
@@ -197,7 +198,7 @@ class IntId : public Printable<IntId> {
   static_assert(MaxValue    == 0b0000'0000'0011'1111'1111'1111'1111'1111);
   static_assert(ZeroIndexId == 0b1111'1111'1110'0000'0000'0000'0000'0000);
   static_assert(MinValue    == 0b1111'1111'1110'0000'0000'0000'0000'0001);
-  static_assert(InvalidId   == 0b1000'0000'0000'0000'0000'0000'0000'0000);
+  static_assert(NoneId      == 0b1000'0000'0000'0000'0000'0000'0000'0000);
   // clang-format on
 
   constexpr explicit IntId(int32_t id) : id_(id) {}
@@ -205,12 +206,12 @@ class IntId : public Printable<IntId> {
   int32_t id_;
 };
 
-constexpr IntId IntId::Invalid(IntId::InvalidId);
+constexpr IntId IntId::None(IntId::NoneId);
 
-// Note that we initialize the invalid index in a constexpr context which
+// Note that we initialize the `None` index in a constexpr context which
 // ensures there is no UB in forming it. This helps ensure all the ID -> index
-// conversions are correct because the invalid ID is at the limit of that range.
-constexpr int32_t IntId::InvalidIndex = Invalid.AsIndex();
+// conversions are correct because the `None` ID is at the limit of that range.
+constexpr int32_t IntId::NoneIndex = None.AsIndex();
 
 // A canonicalizing value store with deep optimizations for integers.
 //
@@ -246,7 +247,7 @@ class IntStore {
   // necessary to represent it.
   auto Add(int64_t value) -> IntId {
     // First try directly making this into an ID.
-    if (IntId id = TryMakeValue(value); id.is_valid()) [[likely]] {
+    if (IntId id = TryMakeValue(value); id.has_value()) [[likely]] {
       return id;
     }
 
@@ -258,7 +259,7 @@ class IntStore {
   // `APInt` if necessary to represent it.
   auto AddSigned(llvm::APInt value) -> IntId {
     // First try directly making this into an ID.
-    if (IntId id = TryMakeSignedValue(value); id.is_valid()) [[likely]] {
+    if (IntId id = TryMakeSignedValue(value); id.has_value()) [[likely]] {
       return id;
     }
 
@@ -271,7 +272,7 @@ class IntStore {
   // represent it.
   auto AddUnsigned(llvm::APInt value) -> IntId {
     // First try directly making this into an ID.
-    if (IntId id = TryMakeUnsignedValue(value); id.is_valid()) [[likely]] {
+    if (IntId id = TryMakeUnsignedValue(value); id.has_value()) [[likely]] {
       return id;
     }
 
@@ -284,7 +285,7 @@ class IntStore {
   // This will always be a signed `APInt` with a canonical bit width for the
   // specific integer value in question.
   auto Get(IntId id) const -> llvm::APInt {
-    if (id.is_value()) [[likely]] {
+    if (id.is_embedded_value()) [[likely]] {
       return llvm::APInt(MinAPWidth, id.AsValue(), /*isSigned=*/true);
     }
     return values_.Get(APIntId(id.AsIndex()));
@@ -319,9 +320,9 @@ class IntStore {
 
   // Accepts a signed `int64_t` and uses the mathematical signed integer value
   // of it as the integer value to lookup. Returns the canonical ID for that
-  // value or returns invalid if not in the store.
+  // value or returns `None` if not in the store.
   auto Lookup(int64_t value) const -> IntId {
-    if (IntId id = TryMakeValue(value); id.is_valid()) [[likely]] {
+    if (IntId id = TryMakeValue(value); id.has_value()) [[likely]] {
       return id;
     }
 
@@ -329,10 +330,10 @@ class IntStore {
     return LookupLarge(value);
   }
 
-  // Looks up the canonical ID for this signed integer value, or returns invalid
+  // Looks up the canonical ID for this signed integer value, or returns `None`
   // if not in the store.
   auto LookupSigned(llvm::APInt value) const -> IntId {
-    if (IntId id = TryMakeSignedValue(value); id.is_valid()) [[likely]] {
+    if (IntId id = TryMakeSignedValue(value); id.has_value()) [[likely]] {
       return id;
     }
 
@@ -361,45 +362,45 @@ class IntStore {
   struct APIntId : IdBase<APIntId> {
     static constexpr llvm::StringLiteral Label = "ap_int";
     using ValueType = llvm::APInt;
-    static const APIntId Invalid;
+    static const APIntId None;
     using IdBase::IdBase;
   };
 
   static constexpr int MinAPWidth = 64;
 
-  static auto MakeIndexOrInvalid(int index) -> IntId {
-    CARBON_DCHECK(index >= 0 && index <= IntId::InvalidIndex);
+  static auto MakeIndexOrNone(int index) -> IntId {
+    CARBON_DCHECK(index >= 0 && index <= IntId::NoneIndex);
     return IntId(IntId::ZeroIndexId - index);
   }
 
   // Tries to make a signed 64-bit integer into an embedded value in the ID, and
-  // if unable to do that returns the `Invalid` ID.
+  // if unable to do that returns the `None` ID.
   static auto TryMakeValue(int64_t value) -> IntId {
     if (IntId::MinValue <= value && value <= IntId::MaxValue) {
       return IntId(value);
     }
 
-    return IntId::Invalid;
+    return IntId::None;
   }
 
   // Tries to make a signed APInt into an embedded value in the ID, and if
-  // unable to do that returns the `Invalid` ID.
+  // unable to do that returns the `None` ID.
   static auto TryMakeSignedValue(llvm::APInt value) -> IntId {
     if (value.sge(IntId::MinValue) && value.sle(IntId::MaxValue)) {
       return IntId(value.getSExtValue());
     }
 
-    return IntId::Invalid;
+    return IntId::None;
   }
 
   // Tries to make an unsigned APInt into an embedded value in the ID, and if
-  // unable to do that returns the `Invalid` ID.
+  // unable to do that returns the `None` ID.
   static auto TryMakeUnsignedValue(llvm::APInt value) -> IntId {
     if (value.ule(IntId::MaxValue)) {
       return IntId(value.getZExtValue());
     }
 
-    return IntId::Invalid;
+    return IntId::None;
   }
 
   // Canonicalize an incoming signed APInt to the correct bit width.
@@ -423,8 +424,7 @@ class IntStore {
   CanonicalValueStore<APIntId> values_;
 };
 
-constexpr IntStore::APIntId IntStore::APIntId::Invalid(
-    IntId::Invalid.AsIndex());
+constexpr IntStore::APIntId IntStore::APIntId::None(IntId::None.AsIndex());
 
 }  // namespace Carbon
 

+ 7 - 7
toolchain/base/int_test.cpp

@@ -43,7 +43,7 @@ TEST(IntStore, Basic) {
 
   for (IntId id :
        {id_0, id_1, id_2, id_42, id_n1, id_n42, id_nines, id_max64, id_min64}) {
-    ASSERT_TRUE(id.is_valid());
+    ASSERT_TRUE(id.has_value());
   }
 
   // Small values should be embedded.
@@ -55,11 +55,11 @@ TEST(IntStore, Basic) {
   EXPECT_THAT(id_n42.AsValue(), Eq(-42));
 
   // Rest should be indices as they don't fit as embedded values.
-  EXPECT_TRUE(!id_nines.is_value());
+  EXPECT_TRUE(!id_nines.is_embedded_value());
   EXPECT_TRUE(id_nines.is_index());
-  EXPECT_TRUE(!id_max64.is_value());
+  EXPECT_TRUE(!id_max64.is_embedded_value());
   EXPECT_TRUE(id_max64.is_index());
-  EXPECT_TRUE(!id_min64.is_value());
+  EXPECT_TRUE(!id_min64.is_embedded_value());
   EXPECT_TRUE(id_min64.is_index());
 
   // And round tripping all the way through the store should work.
@@ -77,7 +77,7 @@ TEST(IntStore, Basic) {
 // Helper struct to hold test values and the resulting IDs.
 struct APAndId {
   llvm::APInt ap;
-  IntId id = IntId::Invalid;
+  IntId id = IntId::None;
 };
 
 TEST(IntStore, APSigned) {
@@ -107,7 +107,7 @@ TEST(IntStore, APSigned) {
   };
   for (auto& [ap, id] : ap_and_ids) {
     id = ints.AddSigned(ap);
-    ASSERT_TRUE(id.is_valid()) << ap;
+    ASSERT_TRUE(id.has_value()) << ap;
   }
 
   for (const auto& [ap, id] : ap_and_ids) {
@@ -139,7 +139,7 @@ TEST(IntStore, APUnsigned) {
   };
   for (auto& [ap, id] : ap_and_ids) {
     id = ints.AddUnsigned(ap);
-    ASSERT_TRUE(id.is_valid()) << ap;
+    ASSERT_TRUE(id.has_value()) << ap;
   }
 
   for (const auto& [ap, id] : ap_and_ids) {

+ 10 - 10
toolchain/base/value_ids.h

@@ -45,41 +45,41 @@ struct Real : public Printable<Real> {
 struct FloatId : public IdBase<FloatId> {
   static constexpr llvm::StringLiteral Label = "float";
   using ValueType = llvm::APFloat;
-  static const FloatId Invalid;
+  static const FloatId None;
   using IdBase::IdBase;
 };
-constexpr FloatId FloatId::Invalid(FloatId::InvalidIndex);
+constexpr FloatId FloatId::None(FloatId::NoneIndex);
 
 // Corresponds to a Real value.
 struct RealId : public IdBase<RealId> {
   static constexpr llvm::StringLiteral Label = "real";
   using ValueType = Real;
-  static const RealId Invalid;
+  static const RealId None;
   using IdBase::IdBase;
 };
-constexpr RealId RealId::Invalid(RealId::InvalidIndex);
+constexpr RealId RealId::None(RealId::NoneIndex);
 
 // Corresponds to StringRefs for identifiers.
 //
-// `NameId` relies on the values of this type other than `Invalid` all being
+// `NameId` relies on the values of this type other than `None` all being
 // non-negative.
 struct IdentifierId : public IdBase<IdentifierId> {
   static constexpr llvm::StringLiteral Label = "identifier";
   using ValueType = llvm::StringRef;
-  static const IdentifierId Invalid;
+  static const IdentifierId None;
   using IdBase::IdBase;
 };
-constexpr IdentifierId IdentifierId::Invalid(IdentifierId::InvalidIndex);
+constexpr IdentifierId IdentifierId::None(IdentifierId::NoneIndex);
 
 // Corresponds to StringRefs for string literals.
 struct StringLiteralValueId : public IdBase<StringLiteralValueId> {
   static constexpr llvm::StringLiteral Label = "string";
   using ValueType = llvm::StringRef;
-  static const StringLiteralValueId Invalid;
+  static const StringLiteralValueId None;
   using IdBase::IdBase;
 };
-constexpr StringLiteralValueId StringLiteralValueId::Invalid(
-    StringLiteralValueId::InvalidIndex);
+constexpr StringLiteralValueId StringLiteralValueId::None(
+    StringLiteralValueId::NoneIndex);
 
 }  // namespace Carbon
 

+ 2 - 2
toolchain/base/value_store.h

@@ -123,7 +123,7 @@ class CanonicalValueStore {
   // Returns the value for an ID.
   auto Get(IdT id) const -> ConstRefType { return values_.Get(id); }
 
-  // Looks up the canonical ID for a value, or returns invalid if not in the
+  // Looks up the canonical ID for a value, or returns `None` if not in the
   // store.
   auto Lookup(ValueType value) const -> IdT;
 
@@ -183,7 +183,7 @@ auto CanonicalValueStore<IdT>::Lookup(ValueType value) const -> IdT {
   if (auto result = set_.Lookup(value, KeyContext(values_.array_ref()))) {
     return result.key();
   }
-  return IdT::Invalid;
+  return IdT::None;
 }
 
 template <typename IdT>

+ 10 - 10
toolchain/base/value_store_test.cpp

@@ -27,8 +27,8 @@ TEST(ValueStore, Real) {
   RealId id1 = reals.Add(real1);
   RealId id2 = reals.Add(real2);
 
-  ASSERT_TRUE(id1.is_valid());
-  ASSERT_TRUE(id2.is_valid());
+  ASSERT_TRUE(id1.has_value());
+  ASSERT_TRUE(id2.has_value());
   EXPECT_THAT(id1, Not(Eq(id2)));
 
   const auto& real1_copy = reals.Get(id1);
@@ -50,8 +50,8 @@ TEST(ValueStore, Float) {
   FloatId id1 = floats.Add(float1);
   FloatId id2 = floats.Add(float2);
 
-  ASSERT_TRUE(id1.is_valid());
-  ASSERT_TRUE(id2.is_valid());
+  ASSERT_TRUE(id1.has_value());
+  ASSERT_TRUE(id2.has_value());
   EXPECT_THAT(id1, Not(Eq(id2)));
 
   EXPECT_THAT(floats.Get(id1).compare(float1), Eq(llvm::APFloatBase::cmpEqual));
@@ -69,15 +69,15 @@ TEST(ValueStore, Identifiers) {
   auto a_id = identifiers.Add(a);
   auto b_id = identifiers.Add(b);
 
-  ASSERT_TRUE(a_id.is_valid());
-  ASSERT_TRUE(b_id.is_valid());
+  ASSERT_TRUE(a_id.has_value());
+  ASSERT_TRUE(b_id.has_value());
   EXPECT_THAT(a_id, Not(Eq(b_id)));
 
   EXPECT_THAT(identifiers.Get(a_id), Eq(a));
   EXPECT_THAT(identifiers.Get(b_id), Eq(b));
 
   EXPECT_THAT(identifiers.Lookup(a), Eq(a_id));
-  EXPECT_THAT(identifiers.Lookup("c"), Eq(IdentifierId::Invalid));
+  EXPECT_THAT(identifiers.Lookup("c"), Eq(IdentifierId::None));
 }
 
 TEST(ValueStore, StringLiterals) {
@@ -88,15 +88,15 @@ TEST(ValueStore, StringLiterals) {
   auto a_id = string_literals.Add(a);
   auto b_id = string_literals.Add(b);
 
-  ASSERT_TRUE(a_id.is_valid());
-  ASSERT_TRUE(b_id.is_valid());
+  ASSERT_TRUE(a_id.has_value());
+  ASSERT_TRUE(b_id.has_value());
   EXPECT_THAT(a_id, Not(Eq(b_id)));
 
   EXPECT_THAT(string_literals.Get(a_id), Eq(a));
   EXPECT_THAT(string_literals.Get(b_id), Eq(b));
 
   EXPECT_THAT(string_literals.Lookup(a), Eq(a_id));
-  EXPECT_THAT(string_literals.Lookup("c"), Eq(StringLiteralValueId::Invalid));
+  EXPECT_THAT(string_literals.Lookup("c"), Eq(StringLiteralValueId::None));
 }
 
 }  // namespace

+ 10 - 10
toolchain/check/call.cpp

@@ -35,7 +35,7 @@ enum class EntityKind : uint8_t {
 // `self_id` and `arg_ids` are the self argument and explicit arguments in the
 // call.
 //
-// Returns a `SpecificId` for the specific callee, `SpecificId::Invalid` if the
+// Returns a `SpecificId` for the specific callee, `SpecificId::None` if the
 // callee is not generic, or `nullopt` if an error has been diagnosed.
 static auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,
                                 const SemIR::EntityWithParamsBase& entity,
@@ -67,13 +67,13 @@ static auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,
   }
 
   // Perform argument deduction.
-  auto specific_id = SemIR::SpecificId::Invalid;
-  if (entity.generic_id.is_valid()) {
+  auto specific_id = SemIR::SpecificId::None;
+  if (entity.generic_id.has_value()) {
     specific_id = DeduceGenericCallArguments(
         context, loc_id, entity.generic_id, enclosing_specific_id,
         entity.implicit_param_patterns_id, entity.param_patterns_id, self_id,
         arg_ids);
-    if (!specific_id.is_valid()) {
+    if (!specific_id.has_value()) {
       return std::nullopt;
     }
   }
@@ -91,7 +91,7 @@ static auto PerformCallToGenericClass(Context& context, SemIR::LocId loc_id,
   auto callee_specific_id =
       ResolveCalleeInCall(context, loc_id, generic_class,
                           EntityKind::GenericClass, enclosing_specific_id,
-                          /*self_id=*/SemIR::InstId::Invalid, arg_ids);
+                          /*self_id=*/SemIR::InstId::None, arg_ids);
   if (!callee_specific_id) {
     return SemIR::ErrorInst::SingletonInstId;
   }
@@ -111,7 +111,7 @@ static auto PerformCallToGenericInterface(
   auto callee_specific_id =
       ResolveCalleeInCall(context, loc_id, interface,
                           EntityKind::GenericInterface, enclosing_specific_id,
-                          /*self_id=*/SemIR::InstId::Invalid, arg_ids);
+                          /*self_id=*/SemIR::InstId::None, arg_ids);
   if (!callee_specific_id) {
     return SemIR::ErrorInst::SingletonInstId;
   }
@@ -123,7 +123,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
                  llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {
   // Identify the function we're calling.
   auto callee_function = GetCalleeFunction(context.sem_ir(), callee_id);
-  if (!callee_function.function_id.is_valid()) {
+  if (!callee_function.function_id.has_value()) {
     auto type_inst =
         context.types().GetAsInst(context.insts().Get(callee_id).type_id());
     CARBON_KIND_SWITCH(type_inst) {
@@ -157,7 +157,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   if (!callee_specific_id) {
     return SemIR::ErrorInst::SingletonInstId;
   }
-  if (callee_specific_id->is_valid()) {
+  if (callee_specific_id->has_value()) {
     callee_id = context.GetOrAddInst(
         context.insts().GetLocId(callee_id),
         SemIR::SpecificFunction{
@@ -169,7 +169,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   }
 
   // If there is a return slot, build storage for the result.
-  SemIR::InstId return_slot_arg_id = SemIR::InstId::Invalid;
+  SemIR::InstId return_slot_arg_id = SemIR::InstId::None;
   SemIR::ReturnTypeInfo return_info = [&] {
     auto& function = context.functions().Get(callee_function.function_id);
     DiagnosticAnnotationScope annotate_diagnostics(
@@ -192,7 +192,7 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
     case SemIR::InitRepr::None:
       // For functions with an implicit return type, the return type is the
       // empty tuple type.
-      if (!return_info.type_id.is_valid()) {
+      if (!return_info.type_id.has_value()) {
         return_info.type_id = context.GetTupleType({});
       }
       break;

+ 14 - 14
toolchain/check/check.cpp

@@ -31,11 +31,11 @@ static auto GetImportKey(UnitAndImports& unit_info,
                          Parse::Tree::PackagingNames names) -> ImportKey {
   auto* stores = unit_info.unit->value_stores;
   llvm::StringRef package_name =
-      names.package_id.is_valid()  ? stores->identifiers().Get(names.package_id)
-      : file_package_id.is_valid() ? stores->identifiers().Get(file_package_id)
-                                   : "";
+      names.package_id.has_value() ? stores->identifiers().Get(names.package_id)
+      : file_package_id.has_value() ? stores->identifiers().Get(file_package_id)
+                                    : "";
   llvm::StringRef library_name =
-      names.library_id.is_valid()
+      names.library_id.has_value()
           ? stores->string_literal_values().Get(names.library_id)
           : "";
   return {package_name, library_name};
@@ -66,7 +66,7 @@ static auto TrackImport(Map<ImportKey, UnitAndImports*>& api_map,
   const auto& packaging = unit_info.parse_tree().packaging_decl();
 
   IdentifierId file_package_id =
-      packaging ? packaging->names.package_id : IdentifierId::Invalid;
+      packaging ? packaging->names.package_id : IdentifierId::None;
   const auto import_key = GetImportKey(unit_info, file_package_id, import);
   const auto& [import_package_name, import_library_name] = import_key;
 
@@ -112,12 +112,12 @@ static auto TrackImport(Map<ImportKey, UnitAndImports*>& api_map,
     // True if the file's package is implicitly `Main` (by omitting an explicit
     // package name).
     bool is_file_implicit_main =
-        !packaging || !packaging->names.package_id.is_valid();
+        !packaging || !packaging->names.package_id.has_value();
     // True if the import is using implicit "current package" syntax (by
     // omitting an explicit package name).
-    bool is_import_implicit_current_package = !import.package_id.is_valid();
+    bool is_import_implicit_current_package = !import.package_id.has_value();
     // True if the import is using `default` library syntax.
-    bool is_import_default_library = !import.library_id.is_valid();
+    bool is_import_default_library = !import.library_id.has_value();
     // True if the import and file point at the same package, even by
     // incorrectly specifying the current package name to `import`.
     bool is_same_package = is_import_implicit_current_package ||
@@ -232,7 +232,7 @@ static auto BuildApiMapAndDiagnosePackaging(
     const auto& packaging = unit_info.parse_tree().packaging_decl();
     // An import key formed from the `package` or `library` declaration. Or, for
     // Main//default, a placeholder key.
-    auto import_key = packaging ? GetImportKey(unit_info, IdentifierId::Invalid,
+    auto import_key = packaging ? GetImportKey(unit_info, IdentifierId::None,
                                                packaging->names)
                                 // Construct a boring key for Main//default.
                                 : ImportKey{"", ""};
@@ -278,7 +278,7 @@ static auto BuildApiMapAndDiagnosePackaging(
                             "`Main//default` previously provided by `{0}`",
                             std::string);
           // Use the invalid node because there's no node to associate with.
-          unit_info.emitter.Emit(Parse::NodeId::Invalid, DuplicateMainApi,
+          unit_info.emitter.Emit(Parse::NodeId::None, DuplicateMainApi,
                                  prev_filename.str());
         }
       }
@@ -299,13 +299,13 @@ static auto BuildApiMapAndDiagnosePackaging(
             "file extension of `{0:.impl|}.carbon` required for {0:`impl`|api}",
             BoolAsSelect);
         auto diag = unit_info.emitter.Build(
-            packaging ? packaging->names.node_id : Parse::NodeId::Invalid,
+            packaging ? packaging->names.node_id : Parse::NodeId::None,
             IncorrectExtension, is_impl);
         if (is_api_with_impl_ext) {
           CARBON_DIAGNOSTIC(
               IncorrectExtensionImplNote, Note,
               "file extension of `.impl.carbon` only allowed for `impl`");
-          diag.Note(Parse::NodeId::Invalid, IncorrectExtensionImplNote);
+          diag.Note(Parse::NodeId::None, IncorrectExtensionImplNote);
         }
         diag.Emit();
       }
@@ -336,7 +336,7 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
     if (packaging && packaging->is_impl) {
       // An `impl` has an implicit import of its `api`.
       auto implicit_names = packaging->names;
-      implicit_names.package_id = IdentifierId::Invalid;
+      implicit_names.package_id = IdentifierId::None;
       TrackImport(api_map, nullptr, unit_info, implicit_names, fuzzing);
     }
 
@@ -351,7 +351,7 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
       auto prelude_id =
           unit_info.unit->value_stores->string_literal_values().Add("prelude");
       TrackImport(api_map, &explicit_import_map, unit_info,
-                  {.node_id = Parse::InvalidNodeId(),
+                  {.node_id = Parse::NoneNodeId(),
                    .package_id = core_ident_id,
                    .library_id = prelude_id},
                   fuzzing);

+ 15 - 15
toolchain/check/check_unit.cpp

@@ -96,13 +96,13 @@ auto CheckUnit::InitPackageScopeAndImports() -> void {
   // reference.
   auto package_scope_id = context_.name_scopes().Add(
       SemIR::Namespace::PackageInstId, SemIR::NameId::PackageNamespace,
-      SemIR::NameScopeId::Invalid);
+      SemIR::NameScopeId::None);
   CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package);
 
   auto package_inst_id = context_.AddInst<SemIR::Namespace>(
-      Parse::NodeId::Invalid, {.type_id = namespace_type_id,
-                               .name_scope_id = SemIR::NameScopeId::Package,
-                               .import_id = SemIR::InstId::Invalid});
+      Parse::NodeId::None, {.type_id = namespace_type_id,
+                            .name_scope_id = SemIR::NameScopeId::Package,
+                            .import_id = SemIR::InstId::None});
   CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId);
 
   // If there is an implicit `api` import, set it first so that it uses the
@@ -118,13 +118,13 @@ auto CheckUnit::InitPackageScopeAndImports() -> void {
                     .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir});
   } else {
     SetApiImportIR(context_,
-                   {.decl_id = SemIR::InstId::Invalid, .sem_ir = nullptr});
+                   {.decl_id = SemIR::InstId::None, .sem_ir = nullptr});
   }
 
   // Add import instructions for everything directly imported. Implicit imports
   // are handled separately.
   for (auto& package_imports : unit_and_imports_->package_imports) {
-    CARBON_CHECK(!package_imports.import_decl_id.is_valid());
+    CARBON_CHECK(!package_imports.import_decl_id.has_value());
     package_imports.import_decl_id = context_.AddInst<SemIR::ImportDecl>(
         package_imports.node_id, {.package_id = SemIR::NameId::ForIdentifier(
                                       package_imports.package_id)});
@@ -221,7 +221,7 @@ auto CheckUnit::ImportCurrentPackage(SemIR::InstId package_inst_id,
                                      SemIR::TypeId namespace_type_id) -> void {
   // Add imports from the current package.
   auto import_map_lookup =
-      unit_and_imports_->package_imports_map.Lookup(IdentifierId::Invalid);
+      unit_and_imports_->package_imports_map.Lookup(IdentifierId::None);
   if (!import_map_lookup) {
     // Push the scope; there are no names to add.
     context_.scope_stack().Push(package_inst_id, SemIR::NameScopeId::Package);
@@ -240,7 +240,7 @@ auto CheckUnit::ImportCurrentPackage(SemIR::InstId package_inst_id,
                                /*api_imports=*/nullptr));
 
   context_.scope_stack().Push(
-      package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::Invalid,
+      package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,
       context_.name_scopes().Get(SemIR::NameScopeId::Package).has_error());
 }
 
@@ -255,7 +255,7 @@ auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {
   // {Invalid, -1} state remains.
   llvm::SmallVector<std::pair<IdentifierId, int32_t>> api_imports_list;
   api_imports_list.resize(unit_and_imports_->package_imports.size(),
-                          {IdentifierId::Invalid, -1});
+                          {IdentifierId::None, -1});
 
   // When there's an API file, add the mapping to api_imports_list.
   if (unit_and_imports_->api_for_impl) {
@@ -267,7 +267,7 @@ auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {
     for (auto [api_imports_index, api_imports] :
          llvm::enumerate(unit_and_imports_->api_for_impl->package_imports)) {
       // Skip the current package.
-      if (!api_imports.package_id.is_valid()) {
+      if (!api_imports.package_id.has_value()) {
         continue;
       }
       // Translate the package ID from the API file to the implementation file.
@@ -287,15 +287,15 @@ auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {
 
   for (auto [i, api_imports_entry] : llvm::enumerate(api_imports_list)) {
     // These variables are updated after figuring out which imports are present.
-    auto import_decl_id = SemIR::InstId::Invalid;
-    IdentifierId package_id = IdentifierId::Invalid;
+    auto import_decl_id = SemIR::InstId::None;
+    IdentifierId package_id = IdentifierId::None;
     bool has_load_error = false;
 
     // Identify the local package imports if present.
     PackageImports* local_imports = nullptr;
     if (i < unit_and_imports_->package_imports.size()) {
       local_imports = &unit_and_imports_->package_imports[i];
-      if (!local_imports->package_id.is_valid()) {
+      if (!local_imports->package_id.has_value()) {
         // Skip the current package.
         continue;
       }
@@ -359,7 +359,7 @@ auto CheckUnit::ImportCppPackages() -> void {
 auto CheckUnit::ProcessNodeIds() -> bool {
   NodeIdTraversal traversal(context_, vlog_stream_);
 
-  Parse::NodeId node_id = Parse::NodeId::Invalid;
+  Parse::NodeId node_id = Parse::NodeId::None;
 
   // On crash, report which token we were handling.
   PrettyStackTraceFunction node_dumper([&](llvm::raw_ostream& output) {
@@ -421,7 +421,7 @@ auto CheckUnit::CheckRequiredDefinitions() -> void {
       }
       case CARBON_KIND(SemIR::FunctionDecl function_decl): {
         if (context_.functions().Get(function_decl.function_id).definition_id ==
-            SemIR::InstId::Invalid) {
+            SemIR::InstId::None) {
           emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
         }
         break;

+ 1 - 1
toolchain/check/check_unit.h

@@ -37,7 +37,7 @@ struct PackageImports {
   // not specific to a single import.
   Parse::ImportDeclId node_id;
   // The associated `import` instruction. Only valid once a file is checked.
-  SemIR::InstId import_decl_id = SemIR::InstId::Invalid;
+  SemIR::InstId import_decl_id = SemIR::InstId::None;
   // Whether there's an import that failed to load.
   bool has_load_error = false;
   // The list of valid imports.

+ 42 - 43
toolchain/check/context.cpp

@@ -59,7 +59,7 @@ Context::Context(DiagnosticEmitter* emitter,
   // Prepare fields which relate to the number of IRs available for import.
   import_irs().Reserve(imported_ir_count);
   import_ir_constant_values_.reserve(imported_ir_count);
-  check_ir_map_.resize(total_ir_count, SemIR::ImportIRId::Invalid);
+  check_ir_map_.resize(total_ir_count, SemIR::ImportIRId::None);
 
   // Map the builtin `<error>` and `type` type constants to their corresponding
   // special `TypeId` values.
@@ -101,8 +101,8 @@ auto Context::GetOrAddInst(SemIR::LocIdAndInst loc_id_and_inst)
     -> SemIR::InstId {
   if (loc_id_and_inst.loc_id.is_implicit()) {
     auto const_id =
-        TryEvalInst(*this, SemIR::InstId::Invalid, loc_id_and_inst.inst);
-    if (const_id.is_valid()) {
+        TryEvalInst(*this, SemIR::InstId::None, loc_id_and_inst.inst);
+    if (const_id.has_value()) {
       CARBON_VLOG("GetOrAddInst: constant: {0}\n", loc_id_and_inst.inst);
       return constant_values().GetInstId(const_id);
     }
@@ -179,7 +179,7 @@ auto Context::AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst)
     -> SemIR::InstId {
   auto inst_id = sem_ir().insts().AddInNoBlock(loc_id_and_inst);
   CARBON_VLOG("AddPlaceholderInst: {0}\n", loc_id_and_inst.inst);
-  constant_values().Set(inst_id, SemIR::ConstantId::Invalid);
+  constant_values().Set(inst_id, SemIR::ConstantId::None);
   return inst_id;
 }
 
@@ -224,13 +224,13 @@ auto Context::DiagnoseDuplicateName(SemIRLoc dup_def, SemIRLoc prev_def)
 }
 
 auto Context::DiagnosePoisonedName(SemIRLoc loc) -> void {
-  // TODO: Improve the diagnostic to replace NodeId::Invalid with the location
+  // TODO: Improve the diagnostic to replace NodeId::None with the location
   // where the name was poisoned. See discussion in
   // https://github.com/carbon-language/carbon-lang/pull/4654#discussion_r1876607172
   CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error,
                     "name used before it was declared");
   CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, "declared here");
-  emitter_->Build(SemIR::LocId::Invalid, NameUseBeforeDecl)
+  emitter_->Build(SemIR::LocId::None, NameUseBeforeDecl)
       .Note(loc, NameUseBeforeDeclNote)
       .Emit();
 }
@@ -245,10 +245,10 @@ auto Context::DiagnoseMemberNameNotFound(
     SemIRLoc loc, SemIR::NameId name_id,
     llvm::ArrayRef<LookupScope> lookup_scopes) -> void {
   if (lookup_scopes.size() == 1 &&
-      lookup_scopes.front().name_scope_id.is_valid()) {
+      lookup_scopes.front().name_scope_id.has_value()) {
     auto specific_id = lookup_scopes.front().specific_id;
     auto scope_inst_id =
-        specific_id.is_valid()
+        specific_id.has_value()
             ? GetInstForSpecific(*this, specific_id)
             : name_scopes().Get(lookup_scopes.front().name_scope_id).inst_id();
     CARBON_DIAGNOSTIC(MemberNameNotFoundInScope, Error,
@@ -309,7 +309,7 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id,
                               ScopeIndex scope_index) -> void {
   if (auto existing =
           scope_stack().LookupOrAddName(name_id, target_id, scope_index);
-      existing.is_valid()) {
+      existing.has_value()) {
     DiagnoseDuplicateName(target_id, existing);
   }
 }
@@ -318,7 +318,7 @@ auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
                                SemIR::NameScopeId scope_id,
                                ScopeIndex scope_index)
     -> std::pair<SemIR::InstId, bool> {
-  if (!scope_id.is_valid()) {
+  if (!scope_id.has_value()) {
     // Look for a name in the specified scope or a scope nested within it only.
     // There are two cases where the name would be in an outer scope:
     //
@@ -390,7 +390,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
                                 LookupScope{.name_scope_id = lookup_scope_id,
                                             .specific_id = specific_id},
                                 /*required=*/false);
-        non_lexical_result.inst_id.is_valid()) {
+        non_lexical_result.inst_id.has_value()) {
       return non_lexical_result;
     }
   }
@@ -399,16 +399,15 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
     CARBON_DIAGNOSTIC(UsedBeforeInitialization, Error,
                       "`{0}` used before initialization", SemIR::NameId);
     emitter_->Emit(node_id, UsedBeforeInitialization, name_id);
-    return {.specific_id = SemIR::SpecificId::Invalid,
+    return {.specific_id = SemIR::SpecificId::None,
             .inst_id = SemIR::ErrorInst::SingletonInstId};
   }
 
-  if (lexical_result.is_valid()) {
+  if (lexical_result.has_value()) {
     // A lexical scope never needs an associated specific. If there's a
     // lexically enclosing generic, then it also encloses the point of use of
     // the name.
-    return {.specific_id = SemIR::SpecificId::Invalid,
-            .inst_id = lexical_result};
+    return {.specific_id = SemIR::SpecificId::None, .inst_id = lexical_result};
   }
 
   // We didn't find anything at all.
@@ -416,7 +415,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
     DiagnoseNameNotFound(node_id, name_id);
   }
 
-  return {.specific_id = SemIR::SpecificId::Invalid,
+  return {.specific_id = SemIR::SpecificId::None,
           .inst_id = SemIR::ErrorInst::SingletonInstId};
 }
 
@@ -431,7 +430,7 @@ auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
     if (!entry.is_poisoned) {
       LoadImportRef(*this, entry.inst_id);
     } else if (is_being_declared) {
-      entry.inst_id = SemIR::InstId::Invalid;
+      entry.inst_id = SemIR::InstId::None;
     }
     return {entry.inst_id, entry.access_kind, entry.is_poisoned};
   }
@@ -442,7 +441,7 @@ auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
                                        scope.import_ir_scopes(), name_id),
             SemIR::AccessKind::Public};
   }
-  return {SemIR::InstId::Invalid, SemIR::AccessKind::Public};
+  return {SemIR::InstId::None, SemIR::AccessKind::Public};
 }
 
 // Prints diagnostics on invalid qualified name access.
@@ -466,11 +465,11 @@ static auto DiagnoseInvalidQualifiedNameAccess(Context& context, SemIRLoc loc,
   if (access_kind == SemIR::AccessKind::Private && is_parent_access) {
     if (auto base_type_id =
             class_info.GetBaseType(context.sem_ir(), class_type->specific_id);
-        base_type_id.is_valid()) {
+        base_type_id.has_value()) {
       parent_type_id = base_type_id;
     } else if (auto adapted_type_id = class_info.GetAdaptedType(
                    context.sem_ir(), class_type->specific_id);
-               adapted_type_id.is_valid()) {
+               adapted_type_id.has_value()) {
       parent_type_id = adapted_type_id;
     } else {
       CARBON_FATAL("Expected parent for parent access");
@@ -528,7 +527,7 @@ auto Context::AppendLookupScopesForConstant(
   if (auto base_as_namespace = base.TryAs<SemIR::Namespace>()) {
     scopes->push_back(
         LookupScope{.name_scope_id = base_as_namespace->name_scope_id,
-                    .specific_id = SemIR::SpecificId::Invalid});
+                    .specific_id = SemIR::SpecificId::None});
     return true;
   }
   if (auto base_as_class = base.TryAs<SemIR::ClassType>()) {
@@ -563,8 +562,8 @@ auto Context::AppendLookupScopesForConstant(
   }
   if (base_const_id == SemIR::ErrorInst::SingletonConstantId) {
     // Lookup into this scope should fail without producing an error.
-    scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::Invalid,
-                                  .specific_id = SemIR::SpecificId::Invalid});
+    scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None,
+                                  .specific_id = SemIR::SpecificId::None});
     return true;
   }
   // TODO: Per the design, if `base_id` is any kind of type, then lookup should
@@ -584,15 +583,15 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
   // TODO: Support reporting of multiple prohibited access.
   llvm::SmallVector<ProhibitedAccessInfo> prohibited_accesses;
 
-  LookupResult result = {.specific_id = SemIR::SpecificId::Invalid,
-                         .inst_id = SemIR::InstId::Invalid};
+  LookupResult result = {.specific_id = SemIR::SpecificId::None,
+                         .inst_id = SemIR::InstId::None};
   bool has_error = false;
   bool is_parent_access = false;
 
   // Walk this scope and, if nothing is found here, the scopes it extends.
   while (!scopes.empty()) {
     auto [scope_id, specific_id] = scopes.pop_back_val();
-    if (!scope_id.is_valid()) {
+    if (!scope_id.has_value()) {
       has_error = true;
       continue;
     }
@@ -615,7 +614,7 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
       });
     }
 
-    if (!scope_result_id.is_valid() || is_access_prohibited) {
+    if (!scope_result_id.has_value() || is_access_prohibited) {
       // If nothing is found in this scope or if we encountered an invalid
       // access, look in its extended scopes.
       const auto& extended = name_scope.extended_scopes();
@@ -623,7 +622,7 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
       for (auto extended_id : llvm::reverse(extended)) {
         // Substitute into the constant describing the extended scope to
         // determine its corresponding specific.
-        CARBON_CHECK(extended_id.is_valid());
+        CARBON_CHECK(extended_id.has_value());
         LoadImportRef(*this, extended_id);
         SemIR::ConstantId const_id =
             GetConstantValueInSpecific(sem_ir(), specific_id, extended_id);
@@ -644,14 +643,14 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
     }
 
     // If this is our second lookup result, diagnose an ambiguity.
-    if (result.inst_id.is_valid()) {
+    if (result.inst_id.has_value()) {
       CARBON_DIAGNOSTIC(
           NameAmbiguousDueToExtend, Error,
           "ambiguous use of name `{0}` found in multiple extended scopes",
           SemIR::NameId);
       emitter_->Emit(loc_id, NameAmbiguousDueToExtend, name_id);
       // TODO: Add notes pointing to the scopes.
-      return {.specific_id = SemIR::SpecificId::Invalid,
+      return {.specific_id = SemIR::SpecificId::None,
               .inst_id = SemIR::ErrorInst::SingletonInstId};
     }
 
@@ -660,7 +659,7 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
     result.is_poisoned = is_poisoned;
   }
 
-  if (required && !result.inst_id.is_valid()) {
+  if (required && !result.inst_id.has_value()) {
     if (!has_error) {
       if (prohibited_accesses.empty()) {
         DiagnoseMemberNameNotFound(loc_id, name_id, lookup_scopes);
@@ -678,7 +677,7 @@ auto Context::LookupQualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id,
       }
     }
 
-    return {.specific_id = SemIR::SpecificId::Invalid,
+    return {.specific_id = SemIR::SpecificId::None,
             .inst_id = SemIR::ErrorInst::SingletonInstId,
             .is_poisoned = result.is_poisoned};
   }
@@ -703,7 +702,7 @@ static auto GetCorePackage(Context& context, SemIRLoc loc, llvm::StringRef name)
   auto [core_inst_id, _, is_poisoned] = context.LookupNameInExactScope(
       loc, core_name_id, SemIR::NameScopeId::Package,
       context.name_scopes().Get(SemIR::NameScopeId::Package));
-  if (core_inst_id.is_valid()) {
+  if (core_inst_id.has_value()) {
     // We expect it to be a namespace.
     if (auto namespace_inst =
             context.insts().TryGetAs<SemIR::Namespace>(core_inst_id)) {
@@ -717,20 +716,20 @@ static auto GetCorePackage(Context& context, SemIRLoc loc, llvm::StringRef name)
       "`Core.{0}` implicitly referenced here, but package `Core` not found",
       std::string);
   context.emitter().Emit(loc, CoreNotFound, name.str());
-  return SemIR::NameScopeId::Invalid;
+  return SemIR::NameScopeId::None;
 }
 
 auto Context::LookupNameInCore(SemIRLoc loc, llvm::StringRef name)
     -> SemIR::InstId {
   auto core_package_id = GetCorePackage(*this, loc, name);
-  if (!core_package_id.is_valid()) {
+  if (!core_package_id.has_value()) {
     return SemIR::ErrorInst::SingletonInstId;
   }
 
   auto name_id = SemIR::NameId::ForIdentifier(identifiers().Add(name));
   auto [inst_id, _, is_poisoned] = LookupNameInExactScope(
       loc, name_id, core_package_id, name_scopes().Get(core_package_id));
-  if (!inst_id.is_valid()) {
+  if (!inst_id.has_value()) {
     CARBON_DIAGNOSTIC(
         CoreNameNotFound, Error,
         "name `Core.{0}` implicitly referenced here, but not found",
@@ -784,7 +783,7 @@ auto Context::AddConvergenceBlockAndPush(Parse::NodeId node_id, int num_blocks)
       if (new_block_id == SemIR::InstBlockId::Unreachable) {
         new_block_id = inst_blocks().AddDefaultValue();
       }
-      CARBON_CHECK(node_id.is_valid());
+      CARBON_CHECK(node_id.has_value());
       AddInst<SemIR::Branch>(node_id, {.target_id = new_block_id});
     }
     inst_block_stack().Pop();
@@ -1092,12 +1091,12 @@ class TypeCompleter {
           }
           return false;
         }
-        if (inst.specific_id.is_valid()) {
+        if (inst.specific_id.has_value()) {
           ResolveSpecificDefinition(context_, loc_, inst.specific_id);
         }
         if (auto adapted_type_id =
                 class_info.GetAdaptedType(context_.sem_ir(), inst.specific_id);
-            adapted_type_id.is_valid()) {
+            adapted_type_id.has_value()) {
           Push(adapted_type_id);
         } else {
           Push(class_info.GetObjectRepr(context_.sem_ir(), inst.specific_id));
@@ -1275,7 +1274,7 @@ class TypeCompleter {
     // its adapted type.
     if (auto adapted_type_id =
             class_info.GetAdaptedType(context_.sem_ir(), inst.specific_id);
-        adapted_type_id.is_valid()) {
+        adapted_type_id.has_value()) {
       return GetNestedValueRepr(adapted_type_id);
     }
     // Otherwise, the value representation for a class is a pointer to the
@@ -1377,7 +1376,7 @@ auto Context::TryToCompleteType(SemIR::TypeId type_id, SemIRLoc loc,
 
 auto Context::CompleteTypeOrCheckFail(SemIR::TypeId type_id) -> void {
   bool complete =
-      TypeCompleter(*this, SemIR::LocId::Invalid, nullptr).Complete(type_id);
+      TypeCompleter(*this, SemIR::LocId::None, nullptr).Complete(type_id);
   CARBON_CHECK(complete, "Expected {0} to be a complete type",
                types().GetAsInst(type_id));
 }
@@ -1450,7 +1449,7 @@ auto Context::RequireDefinedType(SemIR::TypeId type_id, SemIR::LocId loc_id,
         return false;
       }
 
-      if (interface.specific_id.is_valid()) {
+      if (interface.specific_id.has_value()) {
         ResolveSpecificDefinition(*this, loc_id, interface.specific_id);
       }
     }
@@ -1492,7 +1491,7 @@ static auto GetTypeImpl(Context& context, EachArgT... each_arg)
   // TODO: Remove inst_id parameter from TryEvalInst.
   InstT inst = {SemIR::TypeType::SingletonTypeId, each_arg...};
   return context.GetTypeIdForTypeConstant(
-      TryEvalInst(context, SemIR::InstId::Invalid, inst));
+      TryEvalInst(context, SemIR::InstId::None, inst));
 }
 
 // Gets or forms a type_id for a type, given the instruction kind and arguments,

+ 8 - 8
toolchain/check/context.h

@@ -35,14 +35,14 @@ namespace Carbon::Check {
 struct LookupScope {
   // The name scope in which names are searched.
   SemIR::NameScopeId name_scope_id;
-  // The specific for the name scope, or `Invalid` if the name scope is not
+  // The specific for the name scope, or `None` if the name scope is not
   // defined by a generic or we should perform lookup into the generic itself.
   SemIR::SpecificId specific_id;
 };
 
 // A result produced by name lookup.
 struct LookupResult {
-  // The specific in which the lookup result was found. `Invalid` if the result
+  // The specific in which the lookup result was found. `None` if the result
   // was not found in a specific.
   SemIR::SpecificId specific_id;
   // The declaration that was found by name lookup.
@@ -75,7 +75,7 @@ class Context {
       llvm::function_ref<auto()->Context::DiagnosticBuilder>;
 
   struct LookupNameInExactScopeResult {
-    // The matching entity if found, or invalid if poisoned or not found.
+    // The matching entity if found, or `None` if poisoned or not found.
     SemIR::InstId inst_id;
 
     // The access level required to use inst_id, if it's valid.
@@ -225,12 +225,12 @@ class Context {
   // specified, `scope_index` specifies which lexical scope the name is inserted
   // into, otherwise the name is inserted into the current scope.
   auto AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id,
-                       ScopeIndex scope_index = ScopeIndex::Invalid) -> void;
+                       ScopeIndex scope_index = ScopeIndex::None) -> void;
 
   // Performs name lookup in a specified scope for a name appearing in a
-  // declaration. If scope_id is invalid, performs lookup into the lexical scope
+  // declaration. If scope_id is `None`, performs lookup into the lexical scope
   // specified by scope_index instead. If found, returns the referenced
-  // instruction and false. If poisoned, returns an invalid instruction and
+  // instruction and false. If poisoned, returns an `None` instruction and
   // true.
   // TODO: For poisoned names, return the poisoning instruction.
   auto LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
@@ -242,7 +242,7 @@ class Context {
                              bool required = true) -> LookupResult;
 
   // Performs a name lookup in a specified scope, returning the referenced
-  // instruction. Does not look into extended scopes. Returns an invalid
+  // instruction. Does not look into extended scopes. Returns a `None`
   // instruction if the name is not found.
   //
   // If `is_being_declared` is false, then this is a regular name lookup, and
@@ -521,7 +521,7 @@ class Context {
 
   auto Finalize() -> void;
 
-  // Returns the imported IR ID for an IR, or invalid if not imported.
+  // Returns the imported IR ID for an IR, or `None` if not imported.
   auto GetImportIRId(const SemIR::File& sem_ir) -> SemIR::ImportIRId& {
     return check_ir_map_[sem_ir.check_ir_id().index];
   }

+ 21 - 21
toolchain/check/convert.cpp

@@ -30,7 +30,7 @@
 namespace Carbon::Check {
 
 // Given an initializing expression, find its return slot argument. Returns
-// `Invalid` if there is no return slot, because the initialization is not
+// `None` if there is no return slot, because the initialization is not
 // performed in place.
 static auto FindReturnSlotArgForInitializer(SemIR::File& sem_ir,
                                             SemIR::InstId init_id)
@@ -64,11 +64,11 @@ static auto FindReturnSlotArgForInitializer(SemIR::File& sem_ir,
       case CARBON_KIND(SemIR::Call call): {
         if (!SemIR::ReturnTypeInfo::ForType(sem_ir, call.type_id)
                  .has_return_slot()) {
-          return SemIR::InstId::Invalid;
+          return SemIR::InstId::None;
         }
-        if (!call.args_id.is_valid()) {
+        if (!call.args_id.has_value()) {
           // Argument initialization failed, so we have no return slot.
-          return SemIR::InstId::Invalid;
+          return SemIR::InstId::None;
         }
         return sem_ir.inst_blocks().Get(call.args_id).back();
       }
@@ -83,7 +83,7 @@ static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id,
                                SemIR::InstId target_id,
                                PendingBlock& target_block) -> void {
   auto return_slot_arg_id = FindReturnSlotArgForInitializer(sem_ir, init_id);
-  if (return_slot_arg_id.is_valid()) {
+  if (return_slot_arg_id.has_value()) {
     // Replace the temporary in the return slot with a reference to our target.
     CARBON_CHECK(sem_ir.insts().Get(return_slot_arg_id).kind() ==
                      SemIR::TemporaryStorage::Kind,
@@ -98,12 +98,12 @@ static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id,
 // expression described by `init_id`, and returns the location of the
 // temporary. If `discarded` is `true`, the result is discarded, and no
 // temporary will be created if possible; if no temporary is created, the
-// return value will be `SemIR::InstId::Invalid`.
+// return value will be `SemIR::InstId::None`.
 static auto FinalizeTemporary(Context& context, SemIR::InstId init_id,
                               bool discarded) -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
   auto return_slot_arg_id = FindReturnSlotArgForInitializer(sem_ir, init_id);
-  if (return_slot_arg_id.is_valid()) {
+  if (return_slot_arg_id.has_value()) {
     // The return slot should already have a materialized temporary in it.
     CARBON_CHECK(sem_ir.insts().Get(return_slot_arg_id).kind() ==
                      SemIR::TemporaryStorage::Kind,
@@ -119,7 +119,7 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id,
 
   if (discarded) {
     // Don't invent a temporary that we're going to discard.
-    return SemIR::InstId::Invalid;
+    return SemIR::InstId::None;
   }
 
   // The initializer has no return slot, but we want to produce a temporary
@@ -273,7 +273,7 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
   // Arrays are always initialized in-place. Allocate a temporary as the
   // destination for the array initialization if we weren't given one.
   SemIR::InstId return_slot_arg_id = target.init_id;
-  if (!target.init_id.is_valid()) {
+  if (!target.init_id.has_value()) {
     return_slot_arg_id = target_block->AddInst<SemIR::TemporaryStorage>(
         value_loc_id, {.type_id = target.type_id});
   }
@@ -325,7 +325,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
   // directly. Otherwise, materialize a temporary if needed and index into the
   // result.
   llvm::ArrayRef<SemIR::InstId> literal_elems;
-  auto literal_elems_id = SemIR::InstBlockId::Invalid;
+  auto literal_elems_id = SemIR::InstBlockId::None;
   if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {
     literal_elems_id = tuple_literal->elements_id;
     literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);
@@ -360,7 +360,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
   // of the source.
   // TODO: Annotate diagnostics coming from here with the element index.
   auto new_block =
-      literal_elems_id.is_valid()
+      literal_elems_id.has_value()
           ? SemIR::CopyOnWriteInstBlock(sem_ir, literal_elems_id)
           : SemIR::CopyOnWriteInstBlock(
                 sem_ir, SemIR::CopyOnWriteInstBlock::UninitializedBlock{
@@ -420,7 +420,7 @@ static auto ConvertStructToStructOrClass(Context& context,
   // directly. Otherwise, materialize a temporary if needed and index into the
   // result.
   llvm::ArrayRef<SemIR::InstId> literal_elems;
-  auto literal_elems_id = SemIR::InstBlockId::Invalid;
+  auto literal_elems_id = SemIR::InstBlockId::None;
   if (auto struct_literal = value.TryAs<SemIR::StructLiteral>()) {
     literal_elems_id = struct_literal->elements_id;
     literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);
@@ -468,7 +468,7 @@ static auto ConvertStructToStructOrClass(Context& context,
   // of the source.
   // TODO: Annotate diagnostics coming from here with the element index.
   auto new_block =
-      literal_elems_id.is_valid() && !dest_has_vptr
+      literal_elems_id.has_value() && !dest_has_vptr
           ? SemIR::CopyOnWriteInstBlock(sem_ir, literal_elems_id)
           : SemIR::CopyOnWriteInstBlock(
                 sem_ir, SemIR::CopyOnWriteInstBlock::UninitializedBlock{
@@ -496,7 +496,7 @@ static auto ConvertStructToStructOrClass(Context& context,
       if (auto lookup = src_field_indexes.Lookup(dest_field.name_id)) {
         src_field_index = lookup.value();
       } else {
-        if (literal_elems_id.is_valid()) {
+        if (literal_elems_id.has_value()) {
           CARBON_DIAGNOSTIC(
               StructInitMissingFieldInLiteral, Error,
               "missing value for field `{0}` in struct initialization",
@@ -634,7 +634,7 @@ static auto ComputeInheritancePath(Context& context, SemIRLoc loc,
     auto& derived_class = context.classes().Get(derived_class_type->class_id);
     auto base_type_id = derived_class.GetBaseType(
         context.sem_ir(), derived_class_type->specific_id);
-    if (!base_type_id.is_valid()) {
+    if (!base_type_id.has_value()) {
       result = std::nullopt;
       break;
     }
@@ -741,7 +741,7 @@ static auto GetTransitiveAdaptedType(Context& context, SemIR::TypeId type_id)
     auto& class_info = context.classes().Get(class_type->class_id);
     auto adapted_type_id =
         class_info.GetAdaptedType(context.sem_ir(), class_type->specific_id);
-    if (!adapted_type_id.is_valid()) {
+    if (!adapted_type_id.has_value()) {
       break;
     }
     type_id = adapted_type_id;
@@ -827,7 +827,7 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
           loc_id, {.type_id = foundation_type_id, .source_id = value_id});
 
       auto foundation_init_id = target.init_id;
-      if (foundation_init_id != SemIR::InstId::Invalid) {
+      if (foundation_init_id != SemIR::InstId::None) {
         foundation_init_id = target.init_block->AddInst<SemIR::AsCompatible>(
             loc_id,
             {.type_id = foundation_type_id, .source_id = target.init_id});
@@ -923,7 +923,7 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
             sem_ir.types().TryGetAs<SemIR::StructType>(value_type_id)) {
       if (!context.classes()
                .Get(target_class_type->class_id)
-               .adapt_id.is_valid()) {
+               .adapt_id.has_value()) {
         return ConvertStructToClass(context, *src_struct_type,
                                     *target_class_type, value_id, target);
       }
@@ -1270,16 +1270,16 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
 
   // Find self parameter pattern.
   // TODO: Do this during initial traversal of implicit params.
-  auto self_param_id = SemIR::InstId::Invalid;
+  auto self_param_id = SemIR::InstId::None;
   for (auto implicit_param_id : implicit_param_patterns) {
     if (SemIR::Function::GetNameFromPatternId(
             context.sem_ir(), implicit_param_id) == SemIR::NameId::SelfValue) {
-      CARBON_CHECK(!self_param_id.is_valid());
+      CARBON_CHECK(!self_param_id.has_value());
       self_param_id = implicit_param_id;
     }
   }
 
-  if (self_param_id.is_valid() && !self_id.is_valid()) {
+  if (self_param_id.has_value() && !self_id.has_value()) {
     CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
                       "missing object argument in method call");
     CARBON_DIAGNOSTIC(InCallToFunction, Note, "calling function declared here");

+ 1 - 1
toolchain/check/convert.h

@@ -38,7 +38,7 @@ struct ConversionTarget {
   // The target type for the conversion.
   SemIR::TypeId type_id;
   // For an initializer, the object being initialized.
-  SemIR::InstId init_id = SemIR::InstId::Invalid;
+  SemIR::InstId init_id = SemIR::InstId::None;
   // For an initializer, a block of pending instructions that are needed to
   // form the value of `init_id`, and that can be discarded if no
   // initialization is needed.

+ 3 - 4
toolchain/check/decl_introducer_state.h

@@ -26,18 +26,17 @@ struct DeclIntroducerState {
   // The token kind of the introducer.
   Lex::TokenKind kind;
 
-  // Nodes of modifiers on this declaration, in expected order. `Invalid` if no
+  // Nodes of modifiers on this declaration, in expected order. `None` if no
   // modifier of that kind is present.
   Parse::NodeId
       ordered_modifier_node_ids[static_cast<int8_t>(ModifierOrder::Decl) + 1] =
-          {Parse::NodeId::Invalid, Parse::NodeId::Invalid,
-           Parse::NodeId::Invalid};
+          {Parse::NodeId::None, Parse::NodeId::None, Parse::NodeId::None};
 
   // Invariant: contains just the modifiers represented by `saw_*_modifier`.
   KeywordModifierSet modifier_set = KeywordModifierSet();
 
   // If there's an `extern library` in use, the library name.
-  SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::Invalid;
+  SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::None;
 };
 
 // Stack of `DeclIntroducerState` values, representing all the declaration

+ 16 - 16
toolchain/check/decl_name_stack.cpp

@@ -20,7 +20,7 @@ auto DeclNameStack::NameContext::prev_inst_id() -> SemIR::InstId {
   switch (state) {
     case NameContext::State::Error:
       // The name is invalid and a diagnostic has already been emitted.
-      return SemIR::InstId::Invalid;
+      return SemIR::InstId::None;
 
     case NameContext::State::Empty:
       CARBON_FATAL(
@@ -31,7 +31,7 @@ auto DeclNameStack::NameContext::prev_inst_id() -> SemIR::InstId {
       return resolved_inst_id;
 
     case NameContext::State::Unresolved:
-      return SemIR::InstId::Invalid;
+      return SemIR::InstId::None;
 
     case NameContext::State::Poisoned:
       CARBON_FATAL("Poisoned state should not call prev_inst_id()");
@@ -117,7 +117,7 @@ auto DeclNameStack::Restore(SuspendedName sus) -> void {
   for (auto& suspended_scope : llvm::reverse(sus.scopes)) {
     // Reattempt to resolve the definition of the specific. The generic might
     // have been defined after we suspended this scope.
-    if (suspended_scope.entry.specific_id.is_valid()) {
+    if (suspended_scope.entry.specific_id.has_value()) {
       ResolveSpecificDefinition(*context_, sus.name_context.loc_id,
                                 suspended_scope.entry.specific_id);
     }
@@ -133,7 +133,7 @@ auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id,
       return;
 
     case NameContext::State::Unresolved:
-      if (!name_context.parent_scope_id.is_valid()) {
+      if (!name_context.parent_scope_id.has_value()) {
         context_->AddNameToLookup(name_context.unresolved_name_id, target_id,
                                   name_context.initial_scope_index);
       } else {
@@ -176,7 +176,7 @@ auto DeclNameStack::AddNameOrDiagnose(NameContext name_context,
                                       SemIR::AccessKind access_kind) -> void {
   if (name_context.state == DeclNameStack::NameContext::State::Poisoned) {
     context_->DiagnosePoisonedName(target_id);
-  } else if (auto id = name_context.prev_inst_id(); id.is_valid()) {
+  } else if (auto id = name_context.prev_inst_id(); id.has_value()) {
     context_->DiagnoseDuplicateName(target_id, id);
   } else {
     AddName(name_context, target_id, access_kind);
@@ -188,13 +188,13 @@ auto DeclNameStack::LookupOrAddName(NameContext name_context,
                                     SemIR::AccessKind access_kind)
     -> std::pair<SemIR::InstId, bool> {
   if (name_context.state == NameContext::State::Poisoned) {
-    return {SemIR::InstId::Invalid, true};
+    return {SemIR::InstId::None, true};
   }
-  if (auto id = name_context.prev_inst_id(); id.is_valid()) {
+  if (auto id = name_context.prev_inst_id(); id.has_value()) {
     return {id, false};
   }
   AddName(name_context, target_id, access_kind);
-  return {SemIR::InstId::Invalid, false};
+  return {SemIR::InstId::None, false};
 }
 
 // Push a scope corresponding to a name qualifier. For example, for
@@ -211,7 +211,7 @@ static auto PushNameQualifierScope(Context& context, SemIRLoc loc,
   context.scope_stack().PopIfEmpty();
 
   // When declaring a member of a generic, resolve the self specific.
-  if (specific_id.is_valid()) {
+  if (specific_id.has_value()) {
     ResolveSpecificDefinition(context, loc, specific_id);
   }
 
@@ -237,7 +237,7 @@ auto DeclNameStack::ApplyNameQualifier(const NameComponent& name) -> void {
 
   // Resolve the qualifier as a scope and enter the new scope.
   auto [scope_id, specific_id] = ResolveAsScope(name_context, name);
-  if (scope_id.is_valid()) {
+  if (scope_id.has_value()) {
     PushNameQualifierScope(*context_, name_context.loc_id,
                            name_context.resolved_inst_id, scope_id, specific_id,
                            context_->name_scopes().Get(scope_id).has_error());
@@ -268,7 +268,7 @@ auto DeclNameStack::ApplyAndLookupName(NameContext& name_context,
   if (is_poisoned) {
     name_context.unresolved_name_id = name_id;
     name_context.state = NameContext::State::Poisoned;
-  } else if (!resolved_inst_id.is_valid()) {
+  } else if (!resolved_inst_id.has_value()) {
     // Invalid indicates an unresolved name. Store it and return.
     name_context.unresolved_name_id = name_id;
     name_context.state = NameContext::State::Unresolved;
@@ -374,7 +374,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
                                    const NameComponent& name) const
     -> std::pair<SemIR::NameScopeId, SemIR::SpecificId> {
   constexpr std::pair<SemIR::NameScopeId, SemIR::SpecificId> InvalidResult = {
-      SemIR::NameScopeId::Invalid, SemIR::SpecificId::Invalid};
+      SemIR::NameScopeId::None, SemIR::SpecificId::None};
 
   if (!CheckQualifierIsResolved(*context_, name_context)) {
     return InvalidResult;
@@ -429,9 +429,9 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
       // This is specifically for qualified name handling.
       if (!CheckRedeclParamsMatch(
               *context_, new_params,
-              DeclParams(name_context.resolved_inst_id, Parse::NodeId::Invalid,
-                         Parse::NodeId::Invalid, SemIR::InstBlockId::Invalid,
-                         SemIR::InstBlockId::Invalid))) {
+              DeclParams(name_context.resolved_inst_id, Parse::NodeId::None,
+                         Parse::NodeId::None, SemIR::InstBlockId::None,
+                         SemIR::InstBlockId::None))) {
         return InvalidResult;
       }
       if (scope.is_closed_import()) {
@@ -441,7 +441,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
         // be used as a name qualifier.
         scope.set_is_closed_import(false);
       }
-      return {scope_id, SemIR::SpecificId::Invalid};
+      return {scope_id, SemIR::SpecificId::None};
     }
     default: {
       DiagnoseQualifiedDeclInNonScope(*context_, name_context.loc_id,

+ 6 - 6
toolchain/check/decl_name_stack.h

@@ -100,7 +100,7 @@ class DeclNameStack {
       return {
           .name_id = name_id_for_new_inst(),
           .parent_scope_id = parent_scope_id,
-          .generic_id = SemIR::GenericId::Invalid,
+          .generic_id = SemIR::GenericId::None,
           .first_param_node_id = name.first_param_node_id,
           .last_param_node_id = name.last_param_node_id,
           .pattern_block_id = name.pattern_block_id,
@@ -110,9 +110,9 @@ class DeclNameStack {
           .is_extern = is_extern,
           .extern_library_id = extern_library,
           .non_owning_decl_id =
-              extern_library.is_valid() ? decl_id : SemIR::InstId::Invalid,
+              extern_library.has_value() ? decl_id : SemIR::InstId::None,
           .first_owning_decl_id =
-              extern_library.is_valid() ? SemIR::InstId::Invalid : decl_id,
+              extern_library.has_value() ? SemIR::InstId::None : decl_id,
       };
     }
 
@@ -123,7 +123,7 @@ class DeclNameStack {
     // resolved.
     auto name_id_for_new_inst() -> SemIR::NameId {
       return state == State::Unresolved ? unresolved_name_id
-                                        : SemIR::NameId::Invalid;
+                                        : SemIR::NameId::None;
     }
 
     // The current scope when this name began. This is the scope that we will
@@ -141,7 +141,7 @@ class DeclNameStack {
     SemIR::NameScopeId parent_scope_id;
 
     // The last location ID used.
-    SemIR::LocId loc_id = SemIR::LocId::Invalid;
+    SemIR::LocId loc_id = SemIR::LocId::None;
 
     union {
       // The ID of a resolved qualifier, including both identifiers and
@@ -149,7 +149,7 @@ class DeclNameStack {
       SemIR::InstId resolved_inst_id;
 
       // The ID of an unresolved identifier.
-      SemIR::NameId unresolved_name_id = SemIR::NameId::Invalid;
+      SemIR::NameId unresolved_name_id = SemIR::NameId::None;
     };
   };
 

+ 19 - 20
toolchain/check/deduce.cpp

@@ -50,7 +50,7 @@ class DeductionWorklist {
   // Adds a single (param, arg) deduction of a specific.
   auto Add(SemIR::SpecificId param, SemIR::SpecificId arg,
            bool needs_substitution) -> void {
-    if (!param.is_valid() || !arg.is_valid()) {
+    if (!param.has_value() || !arg.has_value()) {
       return;
     }
     auto& param_specific = context_.specifics().Get(param);
@@ -257,7 +257,7 @@ DeductionContext::DeductionContext(Context& context, SemIR::LocId loc_id,
       diagnose_(diagnose),
       worklist_(context),
       first_deduced_index_(0) {
-  CARBON_CHECK(generic_id.is_valid(),
+  CARBON_CHECK(generic_id.has_value(),
                "Performing deduction for non-generic entity");
 
   // Initialize the deduced arguments to Invalid.
@@ -265,9 +265,9 @@ DeductionContext::DeductionContext(Context& context, SemIR::LocId loc_id,
       context.inst_blocks()
           .Get(context.generics().Get(generic_id_).bindings_id)
           .size(),
-      SemIR::InstId::Invalid);
+      SemIR::InstId::None);
 
-  if (enclosing_specific_id.is_valid()) {
+  if (enclosing_specific_id.has_value()) {
     // Copy any outer generic arguments from the specified instance and prepare
     // to substitute them into the function declaration.
     auto args = context.inst_blocks().Get(
@@ -343,7 +343,7 @@ auto DeductionContext::Deduce() -> bool {
       case CARBON_KIND(SemIR::SymbolicBindingPattern bind): {
         auto& entity_name = context().entity_names().Get(bind.entity_name_id);
         auto index = entity_name.bind_index;
-        if (!index.is_valid()) {
+        if (!index.has_value()) {
           break;
         }
         CARBON_CHECK(
@@ -352,12 +352,12 @@ auto DeductionContext::Deduce() -> bool {
             "Unexpected index {0} for symbolic binding pattern; "
             "expected to be in range [{1}, {2})",
             index.index, first_deduced_index_.index, result_arg_ids_.size());
-        CARBON_CHECK(!result_arg_ids_[index.index].is_valid(),
+        CARBON_CHECK(!result_arg_ids_[index.index].has_value(),
                      "Deduced a value for parameter prior to its declaration");
 
         auto arg_const_inst_id =
             context().constant_values().GetConstantInstId(arg_id);
-        if (!arg_const_inst_id.is_valid()) {
+        if (!arg_const_inst_id.has_value()) {
           if (diagnose_) {
             CARBON_DIAGNOSTIC(CompTimeArgumentNotConstant, Error,
                               "argument for generic parameter is not a "
@@ -382,7 +382,7 @@ auto DeductionContext::Deduce() -> bool {
       case CARBON_KIND(SemIR::BindSymbolicName bind): {
         auto& entity_name = context().entity_names().Get(bind.entity_name_id);
         auto index = entity_name.bind_index;
-        if (!index.is_valid() || index < first_deduced_index_ ||
+        if (!index.has_value() || index < first_deduced_index_ ||
             non_deduced_indexes_[index.index - first_deduced_index_.index]) {
           break;
         }
@@ -393,8 +393,8 @@ auto DeductionContext::Deduce() -> bool {
                      index, result_arg_ids_.size());
         auto arg_const_inst_id =
             context().constant_values().GetConstantInstId(arg_id);
-        if (arg_const_inst_id.is_valid()) {
-          if (result_arg_ids_[index.index].is_valid() &&
+        if (arg_const_inst_id.has_value()) {
+          if (result_arg_ids_[index.index].has_value() &&
               result_arg_ids_[index.index] != arg_const_inst_id) {
             if (diagnose_) {
               // TODO: Include the two different deduced values.
@@ -446,7 +446,7 @@ auto DeductionContext::Deduce() -> bool {
     // We didn't manage to deduce against the syntactic form of the parameter.
     // Convert it to a canonical constant value and try deducing against that.
     auto param_const_id = context().constant_values().Get(param_id);
-    if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) {
+    if (!param_const_id.has_value() || !param_const_id.is_symbolic()) {
       // It's not a symbolic constant. There's nothing here to deduce.
       continue;
     }
@@ -460,7 +460,7 @@ auto DeductionContext::Deduce() -> bool {
     // If we've not yet substituted into the parameter, do so now and try again.
     if (needs_substitution) {
       param_const_id = SubstConstant(context(), param_const_id, substitutions_);
-      if (!param_const_id.is_valid() || !param_const_id.is_symbolic()) {
+      if (!param_const_id.has_value() || !param_const_id.is_symbolic()) {
         continue;
       }
       Add(context().constant_values().GetInstId(param_const_id), arg_id,
@@ -476,7 +476,7 @@ auto DeductionContext::CheckDeductionIsComplete() -> bool {
   for (auto [i, deduced_arg_id] :
        llvm::enumerate(llvm::ArrayRef(result_arg_ids_)
                            .drop_front(first_deduced_index_.index))) {
-    if (!deduced_arg_id.is_valid()) {
+    if (!deduced_arg_id.has_value()) {
       if (diagnose_) {
         auto binding_index = first_deduced_index_.index + i;
         auto binding_id = context().inst_blocks().Get(
@@ -524,21 +524,20 @@ auto DeduceGenericCallArguments(
   deduction.AddAll(params_id, arg_ids, /*needs_substitution=*/true);
 
   if (!deduction.Deduce() || !deduction.CheckDeductionIsComplete()) {
-    return SemIR::SpecificId::Invalid;
+    return SemIR::SpecificId::None;
   }
 
   return deduction.MakeSpecific();
 }
 
 // Deduces the impl arguments to use in a use of a parameterized impl. Returns
-// `Invalid` if deduction fails.
+// `None` if deduction fails.
 auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
                          const SemIR::Impl& impl, SemIR::ConstantId self_id,
                          SemIR::ConstantId constraint_id) -> SemIR::SpecificId {
-  DeductionContext deduction(
-      context, loc_id, impl.generic_id,
-      /*enclosing_specific_id=*/SemIR::SpecificId::Invalid,
-      /*diagnose=*/false);
+  DeductionContext deduction(context, loc_id, impl.generic_id,
+                             /*enclosing_specific_id=*/SemIR::SpecificId::None,
+                             /*diagnose=*/false);
 
   // Prepare to perform deduction of the type and interface.
   deduction.Add(impl.self_id, context.constant_values().GetInstId(self_id),
@@ -548,7 +547,7 @@ auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
                 /*needs_substitution=*/false);
 
   if (!deduction.Deduce() || !deduction.CheckDeductionIsComplete()) {
-    return SemIR::SpecificId::Invalid;
+    return SemIR::SpecificId::None;
   }
 
   return deduction.MakeSpecific();

+ 1 - 1
toolchain/check/deduce.h

@@ -21,7 +21,7 @@ auto DeduceGenericCallArguments(Context& context, SemIR::LocId loc_id,
     -> SemIR::SpecificId;
 
 // Deduces the impl arguments to use in a use of a parameterized impl. Returns
-// `Invalid` if deduction fails.
+// `None` if deduction fails.
 auto DeduceImplArguments(Context& context, SemIR::LocId loc_id,
                          const SemIR::Impl& impl, SemIR::ConstantId self_id,
                          SemIR::ConstantId constraint_id) -> SemIR::SpecificId;

+ 1 - 1
toolchain/check/dump.cpp

@@ -30,7 +30,7 @@
 namespace Carbon::Check {
 
 static auto DumpNoNewline(const Context& context, SemIR::LocId loc_id) -> void {
-  if (!loc_id.is_valid()) {
+  if (!loc_id.has_value()) {
     llvm::errs() << "LocId(invalid)";
     return;
   }

+ 50 - 49
toolchain/check/eval.cpp

@@ -33,7 +33,7 @@ class EvalContext {
  public:
   explicit EvalContext(
       Context& context, SemIRLoc fallback_loc,
-      SemIR::SpecificId specific_id = SemIR::SpecificId::Invalid,
+      SemIR::SpecificId specific_id = SemIR::SpecificId::None,
       std::optional<SpecificEvalInfo> specific_eval_info = std::nullopt)
       : context_(context),
         fallback_loc_(fallback_loc),
@@ -51,7 +51,8 @@ class EvalContext {
   // is one, and otherwise the fallback location.
   auto GetDiagnosticLoc(llvm::ArrayRef<SemIR::InstId> inst_ids) -> SemIRLoc {
     for (auto inst_id : inst_ids) {
-      if (inst_id.is_valid() && context_.insts().GetLocId(inst_id).is_valid()) {
+      if (inst_id.has_value() &&
+          context_.insts().GetLocId(inst_id).has_value()) {
         return inst_id;
       }
     }
@@ -59,11 +60,11 @@ class EvalContext {
   }
 
   // Gets the value of the specified compile-time binding in this context.
-  // Returns `Invalid` if the value is not fixed in this context.
+  // Returns `None` if the value is not fixed in this context.
   auto GetCompileTimeBindValue(SemIR::CompileTimeBindIndex bind_index)
       -> SemIR::ConstantId {
-    if (!bind_index.is_valid() || !specific_id_.is_valid()) {
-      return SemIR::ConstantId::Invalid;
+    if (!bind_index.has_value() || !specific_id_.has_value()) {
+      return SemIR::ConstantId::None;
     }
 
     const auto& specific = specifics().Get(specific_id_);
@@ -72,7 +73,7 @@ class EvalContext {
     // Bindings past the ones with known arguments can appear as local
     // bindings of entities declared within this generic.
     if (static_cast<size_t>(bind_index.index) >= args.size()) {
-      return SemIR::ConstantId::Invalid;
+      return SemIR::ConstantId::None;
     }
     return constant_values().Get(args[bind_index.index]);
   }
@@ -93,12 +94,12 @@ class EvalContext {
     if (specific_eval_info_) {
       const auto& symbolic_info =
           constant_values().GetSymbolicConstant(const_id);
-      if (symbolic_info.index.is_valid() &&
+      if (symbolic_info.index.has_value() &&
           symbolic_info.generic_id ==
               specifics().Get(specific_id_).generic_id &&
           symbolic_info.index.region() == specific_eval_info_->region) {
         auto inst_id = specific_eval_info_->values[symbolic_info.index.index()];
-        CARBON_CHECK(inst_id.is_valid(),
+        CARBON_CHECK(inst_id.has_value(),
                      "Forward reference in eval block: index {0} referenced "
                      "before evaluation",
                      symbolic_info.index.index());
@@ -338,15 +339,15 @@ static auto GetConstantValue(EvalContext& eval_context, SemIR::TypeId type_id,
 static auto GetConstantValue(EvalContext& eval_context,
                              SemIR::InstBlockId inst_block_id, Phase* phase)
     -> SemIR::InstBlockId {
-  if (!inst_block_id.is_valid()) {
-    return SemIR::InstBlockId::Invalid;
+  if (!inst_block_id.has_value()) {
+    return SemIR::InstBlockId::None;
   }
   auto insts = eval_context.inst_blocks().Get(inst_block_id);
   llvm::SmallVector<SemIR::InstId> const_insts;
   for (auto inst_id : insts) {
     auto const_inst_id = GetConstantValue(eval_context, inst_id, phase);
-    if (!const_inst_id.is_valid()) {
-      return SemIR::InstBlockId::Invalid;
+    if (!const_inst_id.has_value()) {
+      return SemIR::InstBlockId::None;
     }
 
     // Once we leave the small buffer, we know the first few elements are all
@@ -368,15 +369,15 @@ static auto GetConstantValue(EvalContext& eval_context,
 static auto GetConstantValue(EvalContext& eval_context,
                              SemIR::StructTypeFieldsId fields_id, Phase* phase)
     -> SemIR::StructTypeFieldsId {
-  if (!fields_id.is_valid()) {
-    return SemIR::StructTypeFieldsId::Invalid;
+  if (!fields_id.has_value()) {
+    return SemIR::StructTypeFieldsId::None;
   }
   auto fields = eval_context.context().struct_type_fields().Get(fields_id);
   llvm::SmallVector<SemIR::StructTypeField> new_fields;
   for (auto field : fields) {
     auto new_type_id = GetConstantValue(eval_context, field.type_id, phase);
-    if (!new_type_id.is_valid()) {
-      return SemIR::StructTypeFieldsId::Invalid;
+    if (!new_type_id.has_value()) {
+      return SemIR::StructTypeFieldsId::None;
     }
 
     // Once we leave the small buffer, we know the first few elements are all
@@ -398,15 +399,15 @@ static auto GetConstantValue(EvalContext& eval_context,
 static auto GetConstantValue(EvalContext& eval_context,
                              SemIR::TypeBlockId type_block_id, Phase* phase)
     -> SemIR::TypeBlockId {
-  if (!type_block_id.is_valid()) {
-    return SemIR::TypeBlockId::Invalid;
+  if (!type_block_id.has_value()) {
+    return SemIR::TypeBlockId::None;
   }
   auto types = eval_context.type_blocks().Get(type_block_id);
   llvm::SmallVector<SemIR::TypeId> new_types;
   for (auto type_id : types) {
     auto new_type_id = GetConstantValue(eval_context, type_id, phase);
-    if (!new_type_id.is_valid()) {
-      return SemIR::TypeBlockId::Invalid;
+    if (!new_type_id.has_value()) {
+      return SemIR::TypeBlockId::None;
     }
 
     // Once we leave the small buffer, we know the first few elements are all
@@ -428,14 +429,14 @@ static auto GetConstantValue(EvalContext& eval_context,
 static auto GetConstantValue(EvalContext& eval_context,
                              SemIR::SpecificId specific_id, Phase* phase)
     -> SemIR::SpecificId {
-  if (!specific_id.is_valid()) {
-    return SemIR::SpecificId::Invalid;
+  if (!specific_id.has_value()) {
+    return SemIR::SpecificId::None;
   }
 
   const auto& specific = eval_context.specifics().Get(specific_id);
   auto args_id = GetConstantValue(eval_context, specific.args_id, phase);
-  if (!args_id.is_valid()) {
-    return SemIR::SpecificId::Invalid;
+  if (!args_id.has_value()) {
+    return SemIR::SpecificId::None;
   }
 
   if (args_id == specific.args_id) {
@@ -474,7 +475,7 @@ static auto ReplaceFieldWithConstantValue(EvalContext& eval_context,
                                           InstT* inst, FieldIdT InstT::*field,
                                           Phase* phase) -> bool {
   auto unwrapped = GetConstantValue(eval_context, inst->*field, phase);
-  if (!unwrapped.is_valid() && (inst->*field).is_valid()) {
+  if (!unwrapped.has_value() && (inst->*field).has_value()) {
     return false;
   }
   inst->*field = unwrapped;
@@ -596,7 +597,7 @@ static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)
   Phase phase = Phase::Template;
   auto index_id = GetConstantValue(eval_context, inst.index_id, &phase);
 
-  if (!index_id.is_valid()) {
+  if (!index_id.has_value()) {
     return MakeNonConstantResult(phase);
   }
   auto index = eval_context.insts().TryGetAs<SemIR::IntValue>(index_id);
@@ -633,7 +634,7 @@ static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)
   }
 
   auto aggregate_id = GetConstantValue(eval_context, inst.array_id, &phase);
-  if (!aggregate_id.is_valid()) {
+  if (!aggregate_id.has_value()) {
     return MakeNonConstantResult(phase);
   }
   auto aggregate =
@@ -729,7 +730,7 @@ static auto PerformIntConvert(Context& context, SemIR::InstId arg_id,
       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);
-  if (bit_width_id.is_valid()) {
+  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.
     bool src_is_signed = context.sem_ir().types().IsSignedInt(
@@ -752,7 +753,7 @@ static auto PerformCheckedIntConvert(Context& context, SemIRLoc loc,
 
   auto [is_signed, bit_width_id] =
       context.sem_ir().types().GetIntTypeInfo(dest_type_id);
-  auto width = bit_width_id.is_valid()
+  auto width = bit_width_id.has_value()
                    ? context.ints().Get(bit_width_id).getZExtValue()
                    : arg_val.getBitWidth();
 
@@ -791,7 +792,7 @@ static auto DiagnoseDivisionByZero(Context& context, SemIRLoc loc) -> void {
 // or the canonical width from the value store if not.
 static auto GetIntAtSuitableWidth(Context& context, IntId int_id,
                                   IntId bit_width_id) -> llvm::APInt {
-  return bit_width_id.is_valid()
+  return bit_width_id.has_value()
              ? context.ints().GetAtWidth(int_id, bit_width_id)
              : context.ints().Get(int_id);
 }
@@ -809,7 +810,7 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
   switch (builtin_kind) {
     case SemIR::BuiltinFunctionKind::IntSNegate:
       if (op_val.isMinSignedValue()) {
-        if (bit_width_id.is_valid()) {
+        if (bit_width_id.has_value()) {
           CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,
                             "integer overflow in negation of {0}", TypedInt);
           context.emitter().Emit(loc, CompileTimeIntegerNegateOverflow,
@@ -823,7 +824,7 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
       op_val.negate();
       break;
     case SemIR::BuiltinFunctionKind::IntUNegate:
-      CARBON_CHECK(bit_width_id.is_valid(), "Unsigned negate on unsized int");
+      CARBON_CHECK(bit_width_id.has_value(), "Unsigned negate on unsized int");
       op_val.negate();
       break;
     case SemIR::BuiltinFunctionKind::IntComplement:
@@ -856,7 +857,7 @@ struct APIntBinaryOperands {
 static auto GetIntsAtSuitableWidth(Context& context, IntId lhs_id, IntId rhs_id,
                                    IntId bit_width_id) -> APIntBinaryOperands {
   // Unsized operands: take the wider of the bit widths.
-  if (!bit_width_id.is_valid()) {
+  if (!bit_width_id.has_value()) {
     APIntBinaryOperands result = {.lhs = context.ints().Get(lhs_id),
                                   .rhs = context.ints().Get(rhs_id)};
     if (result.lhs.getBitWidth() != result.rhs.getBitWidth()) {
@@ -977,7 +978,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
   llvm::APInt lhs_val =
       GetIntAtSuitableWidth(context, lhs.int_id, lhs_bit_width_id);
   const auto& rhs_orig_val = context.ints().Get(rhs.int_id);
-  if (lhs_bit_width_id.is_valid() && rhs_orig_val.uge(lhs_val.getBitWidth())) {
+  if (lhs_bit_width_id.has_value() && rhs_orig_val.uge(lhs_val.getBitWidth())) {
     CARBON_DIAGNOSTIC(
         CompileTimeShiftOutOfRange, Error,
         "shift distance >= type width of {0} in `{1} {2:<<|>>} {3}`", unsigned,
@@ -1006,7 +1007,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
 
   llvm::APInt result_val;
   if (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift) {
-    if (!lhs_bit_width_id.is_valid() && !lhs_val.isZero()) {
+    if (!lhs_bit_width_id.has_value() && !lhs_val.isZero()) {
       // Ensure we don't generate a ridiculously large integer through a bit
       // shift.
       auto width = rhs_orig_val.trySExtValue();
@@ -1032,7 +1033,7 @@ static auto PerformBuiltinIntShiftOp(Context& context, SemIRLoc loc,
     result_val =
         lhs_val.ashr(rhs_orig_val.getLimitedValue(lhs_val.getBitWidth()));
   } else {
-    CARBON_CHECK(lhs_bit_width_id.is_valid(), "Logical shift on unsized int");
+    CARBON_CHECK(lhs_bit_width_id.has_value(), "Logical shift on unsized int");
     result_val =
         lhs_val.lshr(rhs_orig_val.getLimitedValue(lhs_val.getBitWidth()));
   }
@@ -1074,7 +1075,7 @@ static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
   BinaryIntOpResult result =
       ComputeBinaryIntOpResult(builtin_kind, lhs_val, rhs_val);
 
-  if (result.overflow && !bit_width_id.is_valid()) {
+  if (result.overflow && !bit_width_id.has_value()) {
     // Retry with a larger bit width. Most operations can only overflow by one
     // bit, but signed n-bit multiplication can overflow to 2n-1 bits. We don't
     // need to handle unsigned multiplication here because it's not permitted
@@ -1430,7 +1431,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
   // call.
   //
   // TODO: Use a better representation for this.
-  if (call.args_id == SemIR::InstBlockId::Invalid) {
+  if (call.args_id == SemIR::InstBlockId::None) {
     return SemIR::ErrorInst::SingletonConstantId;
   }
 
@@ -1441,7 +1442,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, SemIRLoc loc,
   auto callee_function =
       SemIR::GetCalleeFunction(eval_context.sem_ir(), call.callee_id);
   auto builtin_kind = SemIR::BuiltinFunctionKind::None;
-  if (callee_function.function_id.is_valid()) {
+  if (callee_function.function_id.has_value()) {
     // Calls to builtins might be constant.
     builtin_kind = eval_context.functions()
                        .Get(callee_function.function_id)
@@ -1710,7 +1711,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
           eval_context.context(),
           SemIR::ClassType{.type_id = SemIR::TypeType::SingletonTypeId,
                            .class_id = class_decl.class_id,
-                           .specific_id = SemIR::SpecificId::Invalid},
+                           .specific_id = SemIR::SpecificId::None},
           Phase::Template);
     }
 
@@ -1742,7 +1743,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
       return MakeConstantResult(
           eval_context.context(),
           eval_context.context().FacetTypeFromInterface(
-              interface_decl.interface_id, SemIR::SpecificId::Invalid),
+              interface_decl.interface_id, SemIR::SpecificId::None),
           Phase::Template);
     }
 
@@ -1799,7 +1800,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
           // contains a symbolic context.
 
           auto element = elements[index];
-          if (!element.is_valid()) {
+          if (!element.has_value()) {
             // TODO: Perhaps this should be a `{}` value with incomplete type?
             CARBON_DIAGNOSTIC(ImplAccessMemberBeforeComplete, Error,
                               "accessing member from impl before the end of "
@@ -1853,7 +1854,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
       // argument value.
       if (auto value =
               eval_context.GetCompileTimeBindValue(bind_name.bind_index);
-          value.is_valid()) {
+          value.has_value()) {
         return value;
       }
 
@@ -1876,7 +1877,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
         // argument value.
         if (auto value =
                 eval_context.GetCompileTimeBindValue(bind_name.bind_index);
-            value.is_valid()) {
+            value.has_value()) {
           return value;
         }
         phase = Phase::Symbolic;
@@ -1885,7 +1886,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
       // original, with no equivalent value.
       bind.entity_name_id =
           eval_context.entity_names().MakeCanonical(bind.entity_name_id);
-      bind.value_id = SemIR::InstId::Invalid;
+      bind.value_id = SemIR::InstId::None;
       if (!ReplaceFieldWithConstantValue(
               eval_context, &bind, &SemIR::BindSymbolicName::type_id, &phase)) {
         return MakeNonConstantResult(phase);
@@ -1971,7 +1972,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
                      "Unexpected type_id: {0}, inst: {1}", base_facet_type_id,
                      base_facet_inst);
       }
-      if (typed_inst.requirements_id.is_valid()) {
+      if (typed_inst.requirements_id.has_value()) {
         auto insts = eval_context.inst_blocks().Get(typed_inst.requirements_id);
         for (auto inst_id : insts) {
           if (auto rewrite =
@@ -2114,7 +2115,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
   auto eval_block = context.inst_blocks().Get(eval_block_id);
 
   llvm::SmallVector<SemIR::InstId> result;
-  result.resize(eval_block.size(), SemIR::InstId::Invalid);
+  result.resize(eval_block.size(), SemIR::InstId::None);
 
   EvalContext eval_context(context, loc, specific_id,
                            SpecificEvalInfo{
@@ -2126,7 +2127,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here",
                           InstIdAsType);
-        if (loc.is_inst_id && !loc.inst_id.is_valid()) {
+        if (loc.is_inst_id && !loc.inst_id.has_value()) {
           return;
         }
         builder.Note(loc, ResolvingSpecificHere,
@@ -2137,7 +2138,7 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
     auto const_id = TryEvalInstInContext(eval_context, inst_id,
                                          context.insts().Get(inst_id));
     result[i] = context.constant_values().GetInstId(const_id);
-    CARBON_CHECK(result[i].is_valid());
+    CARBON_CHECK(result[i].has_value());
   }
 
   return context.inst_blocks().Add(result);

+ 2 - 2
toolchain/check/function.cpp

@@ -46,13 +46,13 @@ auto CheckFunctionTypeMatches(Context& context,
         FunctionRedeclReturnTypeDiffersNoReturn, Error,
         "function redeclaration differs because no return type is provided");
     auto diag =
-        new_return_type_id.is_valid()
+        new_return_type_id.has_value()
             ? context.emitter().Build(new_function.latest_decl_id(),
                                       FunctionRedeclReturnTypeDiffers,
                                       new_return_type_id)
             : context.emitter().Build(new_function.latest_decl_id(),
                                       FunctionRedeclReturnTypeDiffersNoReturn);
-    if (prev_return_type_id.is_valid()) {
+    if (prev_return_type_id.has_value()) {
       CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePrevious, Note,
                         "previously declared with return type {0}",
                         SemIR::TypeId);

+ 1 - 1
toolchain/check/function.h

@@ -32,7 +32,7 @@ struct SuspendedFunction {
 auto CheckFunctionTypeMatches(
     Context& context, const SemIR::Function& new_function,
     const SemIR::Function& prev_function,
-    SemIR::SpecificId prev_specific_id = SemIR::SpecificId::Invalid,
+    SemIR::SpecificId prev_specific_id = SemIR::SpecificId::None,
     bool check_syntax = true) -> bool;
 
 // Checks that the return type of the specified function is complete, issuing an

+ 16 - 16
toolchain/check/generic.cpp

@@ -79,7 +79,7 @@ class RebuildGenericConstantInEvalBlockCallbacks final
   // block, and substitute them for the instructions in the eval block.
   auto Subst(SemIR::InstId& inst_id) const -> bool override {
     auto const_id = context_.constant_values().Get(inst_id);
-    if (!const_id.is_valid()) {
+    if (!const_id.has_value()) {
       // An unloaded import ref should never contain anything we need to
       // substitute into. Don't trigger loading it here.
       CARBON_CHECK(
@@ -103,7 +103,7 @@ class RebuildGenericConstantInEvalBlockCallbacks final
       if (const_id != context_.constant_values().Get(result.value())) {
         inst_id = result.value();
       }
-      CARBON_CHECK(inst_id.is_valid());
+      CARBON_CHECK(inst_id.has_value());
       return true;
     }
 
@@ -113,7 +113,7 @@ class RebuildGenericConstantInEvalBlockCallbacks final
             context_.insts().TryGetAs<SemIR::BindSymbolicName>(inst_id)) {
       if (context_.entity_names()
               .Get(binding->entity_name_id)
-              .bind_index.is_valid()) {
+              .bind_index.has_value()) {
         inst_id = Rebuild(inst_id, *binding);
         return true;
       }
@@ -334,7 +334,7 @@ auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId {
                                          .inst_id),
                  context.insts().Get(decl_id));
     context.generic_region_stack().Pop();
-    return SemIR::GenericId::Invalid;
+    return SemIR::GenericId::None;
   }
 
   // Build the new Generic object. Note that we intentionally do not hold a
@@ -346,7 +346,7 @@ auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId {
   SemIR::GenericId generic_id = context.generics().Add(
       SemIR::Generic{.decl_id = decl_id,
                      .bindings_id = bindings_id,
-                     .self_specific_id = SemIR::SpecificId::Invalid});
+                     .self_specific_id = SemIR::SpecificId::None});
   // MakeSelfSpecificId could cause something to be imported, which would
   // invalidate the return value of `context.generics().Get(generic_id)`.
   auto self_specific_id = MakeSelfSpecificId(context, generic_id);
@@ -356,7 +356,7 @@ auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId {
 
 auto FinishGenericDecl(Context& context, SemIRLoc loc,
                        SemIR::GenericId generic_id) -> void {
-  if (!generic_id.is_valid()) {
+  if (!generic_id.has_value()) {
     return;
   }
   auto decl_block_id = MakeGenericEvalBlock(
@@ -371,7 +371,7 @@ auto FinishGenericDecl(Context& context, SemIRLoc loc,
 auto BuildGenericDecl(Context& context, SemIR::InstId decl_id)
     -> SemIR::GenericId {
   SemIR::GenericId generic_id = BuildGeneric(context, decl_id);
-  if (generic_id.is_valid()) {
+  if (generic_id.has_value()) {
     FinishGenericDecl(context, decl_id, generic_id);
   }
   return generic_id;
@@ -386,7 +386,7 @@ auto FinishGenericRedecl(Context& context, SemIR::InstId /*decl_id*/,
 
 auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
     -> void {
-  if (!generic_id.is_valid()) {
+  if (!generic_id.has_value()) {
     // TODO: We can have symbolic constants in a context that had a non-generic
     // declaration, for example if there's a local generic let binding in a
     // function definition. Handle this case somehow -- perhaps by forming
@@ -406,7 +406,7 @@ static auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc,
                                        SemIR::SpecificId specific_id) -> void {
   // If this is the first time we've formed this specific, evaluate its decl
   // block to form information about the specific.
-  if (!context.specifics().Get(specific_id).decl_block_id.is_valid()) {
+  if (!context.specifics().Get(specific_id).decl_block_id.has_value()) {
     // Set a placeholder value as the decl block ID so we won't attempt to
     // recursively resolve the same specific.
     context.specifics().Get(specific_id).decl_block_id =
@@ -430,8 +430,8 @@ auto MakeSpecific(Context& context, SemIRLoc loc, SemIR::GenericId generic_id,
 
 static auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)
     -> SemIR::SpecificId {
-  if (!generic_id.is_valid()) {
-    return SemIR::SpecificId::Invalid;
+  if (!generic_id.has_value()) {
+    return SemIR::SpecificId::None;
   }
 
   auto& generic = context.generics().Get(generic_id);
@@ -463,12 +463,12 @@ auto ResolveSpecificDefinition(Context& context, SemIRLoc loc,
   // TODO: Handle recursive resolution of the same generic definition.
   auto& specific = context.specifics().Get(specific_id);
   auto generic_id = specific.generic_id;
-  CARBON_CHECK(generic_id.is_valid(), "Specific with no generic ID");
+  CARBON_CHECK(generic_id.has_value(), "Specific with no generic ID");
 
-  if (!specific.definition_block_id.is_valid()) {
+  if (!specific.definition_block_id.has_value()) {
     // Evaluate the eval block for the definition of the generic.
     auto& generic = context.generics().Get(generic_id);
-    if (!generic.definition_block_id.is_valid()) {
+    if (!generic.definition_block_id.has_value()) {
       // The generic is not defined yet.
       return false;
     }
@@ -484,7 +484,7 @@ auto ResolveSpecificDefinition(Context& context, SemIRLoc loc,
 
 auto GetInstForSpecific(Context& context, SemIR::SpecificId specific_id)
     -> SemIR::InstId {
-  CARBON_CHECK(specific_id.is_valid());
+  CARBON_CHECK(specific_id.has_value());
   const auto& specific = context.specifics().Get(specific_id);
   const auto& generic = context.generics().Get(specific.generic_id);
   auto decl = context.insts().Get(generic.decl_id);
@@ -499,7 +499,7 @@ auto GetInstForSpecific(Context& context, SemIR::SpecificId specific_id)
     }
     case SemIR::FunctionDecl::Kind: {
       return context.constant_values().GetInstId(
-          TryEvalInst(context, SemIR::InstId::Invalid,
+          TryEvalInst(context, SemIR::InstId::None,
                       SemIR::SpecificFunction{
                           .type_id = context.GetSingletonType(
                               SemIR::SpecificFunctionType::SingletonInstId),

+ 4 - 3
toolchain/check/generic.h

@@ -22,7 +22,7 @@ auto StartGenericDefinition(Context& context) -> void;
 auto DiscardGenericDecl(Context& context) -> void;
 
 // Finish processing a potentially generic declaration and produce a
-// corresponding generic object. Returns SemIR::GenericId::Invalid if this
+// corresponding generic object. Returns SemIR::GenericId::None if this
 // declaration is not actually generic.
 auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId;
 
@@ -66,8 +66,9 @@ inline auto MakeSpecificIfGeneric(Context& context, SemIRLoc loc,
                                   SemIR::GenericId generic_id,
                                   SemIR::InstBlockId args_id)
     -> SemIR::SpecificId {
-  return generic_id.is_valid() ? MakeSpecific(context, loc, generic_id, args_id)
-                               : SemIR::SpecificId::Invalid;
+  return generic_id.has_value()
+             ? MakeSpecific(context, loc, generic_id, args_id)
+             : SemIR::SpecificId::None;
 }
 
 // Builds the specific that describes how the generic should refer to itself.

+ 9 - 9
toolchain/check/global_init.cpp

@@ -29,7 +29,7 @@ auto GlobalInit::Finalize() -> void {
   }
 
   Resume();
-  context_->AddInst<SemIR::Return>(Parse::NodeId::Invalid, {});
+  context_->AddInst<SemIR::Return>(Parse::NodeId::None, {});
   // Pop the GlobalInit block here to finalize it.
   context_->inst_block_stack().Pop();
 
@@ -37,18 +37,18 @@ auto GlobalInit::Finalize() -> void {
   context_->sem_ir().set_global_ctor_id(context_->sem_ir().functions().Add(
       {{.name_id = SemIR::NameId::ForIdentifier(name_id),
         .parent_scope_id = SemIR::NameScopeId::Package,
-        .generic_id = SemIR::GenericId::Invalid,
-        .first_param_node_id = Parse::NodeId::Invalid,
-        .last_param_node_id = Parse::NodeId::Invalid,
+        .generic_id = SemIR::GenericId::None,
+        .first_param_node_id = Parse::NodeId::None,
+        .last_param_node_id = Parse::NodeId::None,
         .pattern_block_id = SemIR::InstBlockId::Empty,
-        .implicit_param_patterns_id = SemIR::InstBlockId::Invalid,
+        .implicit_param_patterns_id = SemIR::InstBlockId::None,
         .param_patterns_id = SemIR::InstBlockId::Empty,
         .call_params_id = SemIR::InstBlockId::Empty,
         .is_extern = false,
-        .extern_library_id = SemIR::LibraryNameId::Invalid,
-        .non_owning_decl_id = SemIR::InstId::Invalid,
-        .first_owning_decl_id = SemIR::InstId::Invalid},
-       {.return_slot_pattern_id = SemIR::InstId::Invalid,
+        .extern_library_id = SemIR::LibraryNameId::None,
+        .non_owning_decl_id = SemIR::InstId::None,
+        .first_owning_decl_id = SemIR::InstId::None},
+       {.return_slot_pattern_id = SemIR::InstId::None,
         .body_block_ids = {SemIR::InstBlockId::GlobalInit}}}));
 }
 

+ 3 - 3
toolchain/check/handle_alias.cpp

@@ -37,10 +37,10 @@ auto HandleParseNode(Context& context, Parse::AliasId /*node_id*/) -> bool {
   auto entity_name_id = context.entity_names().Add(
       {.name_id = name_context.name_id_for_new_inst(),
        .parent_scope_id = name_context.parent_scope_id,
-       .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+       .bind_index = SemIR::CompileTimeBindIndex::None});
 
-  auto alias_type_id = SemIR::TypeId::Invalid;
-  auto alias_value_id = SemIR::InstId::Invalid;
+  auto alias_type_id = SemIR::TypeId::None;
+  auto alias_value_id = SemIR::InstId::None;
   if (SemIR::IsSingletonInstId(expr_id)) {
     // Type (`bool`) and value (`false`) literals provided by the builtin
     // structure should be turned into name references.

+ 15 - 16
toolchain/check/handle_binding_pattern.cpp

@@ -36,8 +36,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
   bool is_generic = node_kind == Parse::NodeKind::CompileTimeBindingPattern;
   if (is_generic) {
     auto inst_id = context.scope_stack().PeekInstId();
-    is_associated_constant =
-        inst_id.is_valid() && context.insts().Is<SemIR::InterfaceDecl>(inst_id);
+    is_associated_constant = inst_id.has_value() &&
+                             context.insts().Is<SemIR::InterfaceDecl>(inst_id);
   }
 
   bool needs_compile_time_binding = is_generic && !is_associated_constant;
@@ -46,8 +46,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
       context.decl_introducer_state_stack().innermost();
 
   auto make_binding_pattern = [&]() -> SemIR::InstId {
-    auto bind_id = SemIR::InstId::Invalid;
-    auto binding_pattern_id = SemIR::InstId::Invalid;
+    auto bind_id = SemIR::InstId::None;
+    auto binding_pattern_id = SemIR::InstId::None;
     // TODO: Eventually the name will need to support associations with other
     // scopes, but right now we don't support qualified names here.
     auto entity_name_id = context.entity_names().Add(
@@ -57,14 +57,13 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
          // constant declaration.
          .bind_index = needs_compile_time_binding
                            ? context.scope_stack().AddCompileTimeBinding()
-                           : SemIR::CompileTimeBindIndex::Invalid});
+                           : SemIR::CompileTimeBindIndex::None});
     if (is_generic) {
       // TODO: Create a `BindTemplateName` instead inside a `template` pattern.
       bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst(
-          name_node,
-          SemIR::BindSymbolicName{.type_id = cast_type_id,
-                                  .entity_name_id = entity_name_id,
-                                  .value_id = SemIR::InstId::Invalid}));
+          name_node, SemIR::BindSymbolicName{.type_id = cast_type_id,
+                                             .entity_name_id = entity_name_id,
+                                             .value_id = SemIR::InstId::None}));
       binding_pattern_id =
           context.AddPatternInst<SemIR::SymbolicBindingPattern>(
               name_node,
@@ -73,7 +72,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
       bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst(
           name_node, SemIR::BindName{.type_id = cast_type_id,
                                      .entity_name_id = entity_name_id,
-                                     .value_id = SemIR::InstId::Invalid}));
+                                     .value_id = SemIR::InstId::None}));
       binding_pattern_id = context.AddPatternInst<SemIR::BindingPattern>(
           name_node,
           {.type_id = cast_type_id, .entity_name_id = entity_name_id});
@@ -133,7 +132,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
         });
     auto binding_id =
         is_generic
-            ? Parse::NodeId::Invalid
+            ? Parse::NodeId::None
             : context.parse_tree().As<Parse::VarBindingPatternId>(node_id);
     auto& class_info = context.classes().Get(parent_class_decl->class_id);
     auto field_type_id =
@@ -141,7 +140,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
     auto field_id = context.AddInst<SemIR::FieldDecl>(
         binding_id, {.type_id = field_type_id,
                      .name_id = name_id,
-                     .index = SemIR::ElementIndex::Invalid});
+                     .index = SemIR::ElementIndex::None});
     context.field_decls_stack().AppendToTop(field_id);
 
     context.node_stack().Push(node_id, field_id);
@@ -167,7 +166,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
     context.entity_names().Add(
         {.name_id = name_id,
          .parent_scope_id = context.scope_stack().PeekNameScopeId(),
-         .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+         .bind_index = SemIR::CompileTimeBindIndex::None});
 
     SemIR::InstId decl_id = context.AddInst<SemIR::AssociatedConstantDecl>(
         context.parse_tree().As<Parse::CompileTimeBindingPatternId>(node_id),
@@ -228,7 +227,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
       // in a function definition. We don't know which kind we have here.
       // TODO: A tuple pattern can appear in other places than function
       // parameters.
-      auto param_pattern_id = SemIR::InstId::Invalid;
+      auto param_pattern_id = SemIR::InstId::None;
       bool had_error = false;
       switch (introducer.kind) {
         case Lex::TokenKind::Fn: {
@@ -273,7 +272,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
             {
                 .type_id = context.insts().Get(pattern_inst_id).type_id(),
                 .subpattern_id = pattern_inst_id,
-                .runtime_index = is_generic ? SemIR::RuntimeParamIndex::Invalid
+                .runtime_index = is_generic ? SemIR::RuntimeParamIndex::None
                                             : SemIR::RuntimeParamIndex::Unknown,
             });
       }
@@ -326,7 +325,7 @@ auto HandleParseNode(Context& context,
     // can represent a block scope, but is also used for other kinds of scopes
     // that aren't necessarily part of an interface or function decl.
     auto scope_inst_id = context.scope_stack().PeekInstId();
-    if (scope_inst_id.is_valid()) {
+    if (scope_inst_id.has_value()) {
       auto scope_inst = context.insts().Get(scope_inst_id);
       if (!scope_inst.Is<SemIR::InterfaceDecl>() &&
           !scope_inst.Is<SemIR::FunctionDecl>()) {

+ 25 - 25
toolchain/check/handle_class.cpp

@@ -87,7 +87,7 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc,
     prev_class.complete_type_witness_id = new_class.complete_type_witness_id;
   }
 
-  if ((prev_import_ir_id.is_valid() && !new_is_import) ||
+  if ((prev_import_ir_id.has_value() && !new_is_import) ||
       (prev_class.is_extern && !new_class.is_extern)) {
     prev_class.first_owning_decl_id = new_class.first_owning_decl_id;
     ReplacePrevInstForMerge(
@@ -113,12 +113,12 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
     return;
   }
 
-  if (!prev_id.is_valid()) {
+  if (!prev_id.has_value()) {
     return;
   }
 
-  auto prev_class_id = SemIR::ClassId::Invalid;
-  auto prev_import_ir_id = SemIR::ImportIRId::Invalid;
+  auto prev_class_id = SemIR::ClassId::None;
+  auto prev_import_ir_id = SemIR::ImportIRId::None;
   auto prev = context.insts().Get(prev_id);
   CARBON_KIND_SWITCH(prev) {
     case CARBON_KIND(SemIR::ClassDecl class_decl): {
@@ -154,7 +154,7 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
       break;
   }
 
-  if (!prev_class_id.is_valid()) {
+  if (!prev_class_id.has_value()) {
     // This is a redeclaration of something other than a class.
     context.DiagnoseDuplicateName(class_decl_id, prev_id);
     return;
@@ -198,7 +198,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
                                is_definition);
 
   bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern);
-  if (introducer.extern_library.is_valid()) {
+  if (introducer.extern_library.has_value()) {
     context.TODO(node_id, "extern library");
   }
   auto inheritance_kind =
@@ -212,7 +212,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
   // Add the class declaration.
   auto class_decl =
       SemIR::ClassDecl{.type_id = SemIR::TypeType::SingletonTypeId,
-                       .class_id = SemIR::ClassId::Invalid,
+                       .class_id = SemIR::ClassId::None,
                        .decl_block_id = decl_block_id};
   auto class_decl_id =
       context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, class_decl));
@@ -220,9 +220,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
   // TODO: Store state regarding is_extern.
   SemIR::Class class_info = {
       name_context.MakeEntityWithParamsBase(name, class_decl_id, is_extern,
-                                            SemIR::LibraryNameId::Invalid),
+                                            SemIR::LibraryNameId::None),
       {// `.self_type_id` depends on the ClassType, so is set below.
-       .self_type_id = SemIR::TypeId::Invalid,
+       .self_type_id = SemIR::TypeId::None,
        .inheritance_kind = inheritance_kind}};
 
   MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl,
@@ -230,7 +230,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
                  introducer.modifier_set.GetAccessKind());
 
   // Create a new class if this isn't a valid redeclaration.
-  bool is_new_class = !class_decl.class_id.is_valid();
+  bool is_new_class = !class_decl.class_id.has_value();
   if (is_new_class) {
     // TODO: If this is an invalid redeclaration of a non-class entity or there
     // was an error in the qualifier, we will have lost track of the class name
@@ -256,7 +256,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
     auto specific_id =
         context.generics().GetSelfSpecific(class_info.generic_id);
     class_info.self_type_id = context.GetTypeIdForTypeConstant(TryEvalInst(
-        context, SemIR::InstId::Invalid,
+        context, SemIR::InstId::None,
         SemIR::ClassType{.type_id = SemIR::TypeType::SingletonTypeId,
                          .class_id = class_decl.class_id,
                          .specific_id = specific_id}));
@@ -285,7 +285,7 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)
   CARBON_CHECK(!class_info.has_definition_started());
   class_info.definition_id = class_decl_id;
   class_info.scope_id = context.name_scopes().Add(
-      class_decl_id, SemIR::NameId::Invalid, class_info.parent_scope_id);
+      class_decl_id, SemIR::NameId::None, class_info.parent_scope_id);
 
   // Enter the class scope.
   context.scope_stack().Push(
@@ -380,7 +380,7 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool {
   }
 
   auto& class_info = context.classes().Get(parent_class_decl->class_id);
-  if (class_info.adapt_id.is_valid()) {
+  if (class_info.adapt_id.has_value()) {
     DiagnoseClassSpecificDeclRepeated(context, node_id, class_info.adapt_id,
                                       Lex::TokenKind::Adapt);
     return true;
@@ -442,7 +442,7 @@ struct BaseInfo {
 };
 constexpr BaseInfo BaseInfo::Error = {
     .type_id = SemIR::ErrorInst::SingletonTypeId,
-    .scope_id = SemIR::NameScopeId::Invalid,
+    .scope_id = SemIR::NameScopeId::None,
     .inst_id = SemIR::ErrorInst::SingletonInstId};
 }  // namespace
 
@@ -487,7 +487,7 @@ static auto CheckBaseType(Context& context, Parse::NodeId node_id,
     DiagnoseBaseIsFinal(context, node_id, base_type_inst_id);
   }
 
-  CARBON_CHECK(base_class_info->scope_id.is_valid(),
+  CARBON_CHECK(base_class_info->scope_id.has_value(),
                "Complete class should have a scope");
   return {.type_id = base_type_id,
           .scope_id = base_class_info->scope_id,
@@ -515,7 +515,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
   }
 
   auto& class_info = context.classes().Get(parent_class_decl->class_id);
-  if (class_info.base_id.is_valid()) {
+  if (class_info.base_id.has_value()) {
     DiagnoseClassSpecificDeclRepeated(context, node_id, class_info.base_id,
                                       Lex::TokenKind::Base);
     return true;
@@ -541,7 +541,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
   class_info.base_id = context.AddInst<SemIR::BaseDecl>(
       node_id, {.type_id = field_type_id,
                 .base_type_inst_id = base_info.inst_id,
-                .index = SemIR::ElementIndex::Invalid});
+                .index = SemIR::ElementIndex::None});
 
   if (base_info.type_id != SemIR::ErrorInst::SingletonTypeId) {
     auto base_class_info = context.classes().Get(
@@ -558,7 +558,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {
   // Extend the class scope with the base class.
   if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
     auto& class_scope = context.name_scopes().Get(class_info.scope_id);
-    if (base_info.scope_id.is_valid()) {
+    if (base_info.scope_id.has_value()) {
       class_scope.AddExtendedScope(base_info.inst_id);
     } else {
       class_scope.set_has_error();
@@ -574,7 +574,7 @@ static auto CheckCompleteAdapterClassType(Context& context,
                                           SemIR::ClassId class_id)
     -> SemIR::InstId {
   const auto& class_info = context.classes().Get(class_id);
-  if (class_info.base_id.is_valid()) {
+  if (class_info.base_id.has_value()) {
     CARBON_DIAGNOSTIC(AdaptWithBase, Error, "adapter with base class");
     CARBON_DIAGNOSTIC(AdaptWithBaseHere, Note, "`base` declaration is here");
     context.emitter()
@@ -618,7 +618,7 @@ static auto CheckCompleteAdapterClassType(Context& context,
   // The object representation of the adapter is the object representation
   // of the adapted type.
   auto adapted_type_id =
-      class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::Invalid);
+      class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::None);
   auto object_repr_id = context.types().GetObjectRepr(adapted_type_id);
 
   return context.AddInst<SemIR::CompleteTypeWitness>(
@@ -659,15 +659,15 @@ static auto AddStructTypeFields(
 static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id,
                                    SemIR::ClassId class_id) -> SemIR::InstId {
   auto& class_info = context.classes().Get(class_id);
-  if (class_info.adapt_id.is_valid()) {
+  if (class_info.adapt_id.has_value()) {
     return CheckCompleteAdapterClassType(context, node_id, class_id);
   }
 
   bool defining_vptr = class_info.is_dynamic;
   auto base_type_id =
-      class_info.GetBaseType(context.sem_ir(), SemIR::SpecificId::Invalid);
+      class_info.GetBaseType(context.sem_ir(), SemIR::SpecificId::None);
   SemIR::Class* base_class_info = nullptr;
-  if (base_type_id.is_valid()) {
+  if (base_type_id.has_value()) {
     // TODO: If the base class is template dependent, we will need to decide
     // whether to add a vptr as part of instantiation.
     base_class_info = TryGetAsClass(context, base_type_id);
@@ -678,7 +678,7 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id,
 
   auto field_decls = context.field_decls_stack().PeekArray();
   llvm::SmallVector<SemIR::StructTypeField> struct_type_fields;
-  struct_type_fields.reserve(defining_vptr + class_info.base_id.is_valid() +
+  struct_type_fields.reserve(defining_vptr + class_info.base_id.has_value() +
                              field_decls.size());
   if (defining_vptr) {
     struct_type_fields.push_back(
@@ -686,7 +686,7 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id,
          .type_id = context.GetPointerType(
              context.GetSingletonType(SemIR::VtableType::SingletonInstId))});
   }
-  if (base_type_id.is_valid()) {
+  if (base_type_id.has_value()) {
     auto base_decl = context.insts().GetAs<SemIR::BaseDecl>(class_info.base_id);
     base_decl.index =
         SemIR::ElementIndex{static_cast<int>(struct_type_fields.size())};

+ 1 - 1
toolchain/check/handle_export.cpp

@@ -36,7 +36,7 @@ auto HandleParseNode(Context& context, Parse::ExportDeclId node_id) -> bool {
   }
 
   auto inst_id = name_context.prev_inst_id();
-  if (!inst_id.is_valid()) {
+  if (!inst_id.has_value()) {
     context.DiagnoseNameNotFound(node_id, name_context.name_id_for_new_inst());
     return true;
   }

+ 19 - 19
toolchain/check/handle_function.cpp

@@ -98,7 +98,7 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc,
     return false;
   }
 
-  if (!prev_function.first_owning_decl_id.is_valid()) {
+  if (!prev_function.first_owning_decl_id.has_value()) {
     prev_function.first_owning_decl_id = new_function.first_owning_decl_id;
   }
   if (new_is_definition) {
@@ -107,7 +107,7 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc,
     prev_function.MergeDefinition(new_function);
     prev_function.return_slot_pattern_id = new_function.return_slot_pattern_id;
   }
-  if ((prev_import_ir_id.is_valid() && !new_is_import)) {
+  if ((prev_import_ir_id.has_value() && !new_is_import)) {
     ReplacePrevInstForMerge(context, new_function.parent_scope_id,
                             prev_function.name_id,
                             new_function.first_owning_decl_id);
@@ -121,12 +121,12 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,
                            SemIR::FunctionDecl& function_decl,
                            SemIR::Function& function_info, bool is_definition)
     -> void {
-  if (!prev_id.is_valid()) {
+  if (!prev_id.has_value()) {
     return;
   }
 
-  auto prev_function_id = SemIR::FunctionId::Invalid;
-  auto prev_import_ir_id = SemIR::ImportIRId::Invalid;
+  auto prev_function_id = SemIR::FunctionId::None;
+  auto prev_import_ir_id = SemIR::ImportIRId::None;
   CARBON_KIND_SWITCH(context.insts().Get(prev_id)) {
     case CARBON_KIND(SemIR::FunctionDecl function_decl): {
       prev_function_id = function_decl.function_id;
@@ -157,7 +157,7 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,
       break;
   }
 
-  if (!prev_function_id.is_valid()) {
+  if (!prev_function_id.has_value()) {
     context.DiagnoseDuplicateName(function_info.latest_decl_id(), prev_id);
     return;
   }
@@ -177,7 +177,7 @@ static auto BuildFunctionDecl(Context& context,
                               Parse::AnyFunctionDeclId node_id,
                               bool is_definition)
     -> std::pair<SemIR::FunctionId, SemIR::InstId> {
-  auto return_slot_pattern_id = SemIR::InstId::Invalid;
+  auto return_slot_pattern_id = SemIR::InstId::None;
   if (auto [return_node, maybe_return_slot_pattern_id] =
           context.node_stack().PopWithNodeIdIf<Parse::NodeKind::ReturnType>();
       maybe_return_slot_pattern_id) {
@@ -185,7 +185,7 @@ static auto BuildFunctionDecl(Context& context,
   }
 
   auto name = PopNameComponent(context, return_slot_pattern_id);
-  if (!name.param_patterns_id.is_valid()) {
+  if (!name.param_patterns_id.has_value()) {
     context.TODO(node_id, "function with positional parameters");
     name.param_patterns_id = SemIR::InstBlockId::Empty;
   }
@@ -217,7 +217,7 @@ static auto BuildFunctionDecl(Context& context,
     if (auto class_decl = parent_scope_inst->TryAs<SemIR::ClassDecl>()) {
       virtual_class_info = &context.classes().Get(class_decl->class_id);
       if (virtual_modifier == SemIR::Function::VirtualModifier::Impl &&
-          !virtual_class_info->base_id.is_valid()) {
+          !virtual_class_info->base_id.has_value()) {
         CARBON_DIAGNOSTIC(ImplWithoutBase, Error, "impl without base class");
         context.emitter().Build(node_id, ImplWithoutBase).Emit();
       }
@@ -236,7 +236,7 @@ static auto BuildFunctionDecl(Context& context,
   // Add the function declaration.
   auto decl_block_id = context.inst_block_stack().Pop();
   auto function_decl = SemIR::FunctionDecl{
-      SemIR::TypeId::Invalid, SemIR::FunctionId::Invalid, decl_block_id};
+      SemIR::TypeId::None, SemIR::FunctionId::None, decl_block_id};
   auto decl_id =
       context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, function_decl));
 
@@ -262,7 +262,7 @@ static auto BuildFunctionDecl(Context& context,
   }
 
   // Create a new function if this isn't a valid redeclaration.
-  if (!function_decl.function_id.is_valid()) {
+  if (!function_decl.function_id.has_value()) {
     if (function_info.is_extern && context.IsImplFile()) {
       DiagnoseExternRequiresDeclInApiFile(context, node_id);
     }
@@ -291,7 +291,7 @@ static auto BuildFunctionDecl(Context& context,
   // Check if we need to add this to name lookup, now that the function decl is
   // done.
   if (name_context.state != DeclNameStack::NameContext::State::Poisoned &&
-      !name_context.prev_inst_id().is_valid()) {
+      !name_context.prev_inst_id().has_value()) {
     // At interface scope, a function declaration introduces an associated
     // function.
     auto lookup_result_id = decl_id;
@@ -310,10 +310,10 @@ static auto BuildFunctionDecl(Context& context,
   if (SemIR::IsEntryPoint(context.sem_ir(), function_decl.function_id)) {
     auto return_type_id = function_info.GetDeclaredReturnType(context.sem_ir());
     // TODO: Update this once valid signatures for the entry point are decided.
-    if (function_info.implicit_param_patterns_id.is_valid() ||
-        !function_info.param_patterns_id.is_valid() ||
+    if (function_info.implicit_param_patterns_id.has_value() ||
+        !function_info.param_patterns_id.has_value() ||
         !context.inst_blocks().Get(function_info.param_patterns_id).empty() ||
-        (return_type_id.is_valid() &&
+        (return_type_id.has_value() &&
          return_type_id != context.GetTupleType({}) &&
          // TODO: Decide on valid return types for `Main.Run`. Perhaps we should
          // have an interface for this.
@@ -346,10 +346,10 @@ static auto CheckFunctionDefinitionSignature(Context& context,
       context.inst_blocks().GetOrEmpty(function.call_params_id);
 
   // Check the return type is complete.
-  if (function.return_slot_pattern_id.is_valid()) {
+  if (function.return_slot_pattern_id.has_value()) {
     CheckFunctionReturnType(
         context, context.insts().GetLocId(function.return_slot_pattern_id),
-        function, SemIR::SpecificId::Invalid);
+        function, SemIR::SpecificId::None);
     params_to_complete = params_to_complete.drop_back();
   }
 
@@ -432,7 +432,7 @@ auto HandleParseNode(Context& context, Parse::FunctionDefinitionId node_id)
   if (context.is_current_position_reachable()) {
     if (context.functions()
             .Get(function_id)
-            .return_slot_pattern_id.is_valid()) {
+            .return_slot_pattern_id.has_value()) {
       CARBON_DIAGNOSTIC(
           MissingReturnStatement, Error,
           "missing `return` at end of function with declared return type");
@@ -510,7 +510,7 @@ static auto IsValidBuiltinDeclaration(Context& context,
 
   // Get the return type. This is `()` if none was specified.
   auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());
-  if (!return_type_id.is_valid()) {
+  if (!return_type_id.has_value()) {
     return_type_id = context.GetTupleType({});
   }
 

+ 19 - 19
toolchain/check/handle_impl.cpp

@@ -73,11 +73,11 @@ auto HandleParseNode(Context& context, Parse::TypeImplAsId node_id) -> bool {
 // TODO: Should this be somewhere more central?
 static auto TryAsClassScope(Context& context, SemIR::NameScopeId scope_id)
     -> std::optional<SemIR::ClassDecl> {
-  if (!scope_id.is_valid()) {
+  if (!scope_id.has_value()) {
     return std::nullopt;
   }
   auto& scope = context.name_scopes().Get(scope_id);
-  if (!scope.inst_id().is_valid()) {
+  if (!scope.inst_id().has_value()) {
     return std::nullopt;
   }
   return context.insts().TryGetAs<SemIR::ClassDecl>(scope.inst_id());
@@ -92,13 +92,13 @@ static auto GetDefaultSelfType(Context& context) -> SemIR::TypeId {
 
   // TODO: This is also valid in a mixin.
 
-  return SemIR::TypeId::Invalid;
+  return SemIR::TypeId::None;
 }
 
 auto HandleParseNode(Context& context, Parse::DefaultSelfImplAsId node_id)
     -> bool {
   auto self_type_id = GetDefaultSelfType(context);
-  if (!self_type_id.is_valid()) {
+  if (!self_type_id.has_value()) {
     CARBON_DIAGNOSTIC(ImplAsOutsideClass, Error,
                       "`impl as` can only be used in a class");
     context.emitter().Emit(node_id, ImplAsOutsideClass);
@@ -143,7 +143,7 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node,
     return;
   }
 
-  if (params_node.is_valid()) {
+  if (params_node.has_value()) {
     CARBON_DIAGNOSTIC(ExtendImplForall, Error,
                       "cannot `extend` a parameterized `impl`");
     context.emitter().Emit(extend_node, ExtendImplForall);
@@ -202,7 +202,7 @@ static auto PopImplIntroducerAndParamsAsNameComponent(
     // because `impl`s are never actually called at runtime.
     auto call_params_id =
         CalleePatternMatch(context, *implicit_param_patterns_id,
-                           SemIR::InstBlockId::Invalid, SemIR::InstId::Invalid);
+                           SemIR::InstBlockId::None, SemIR::InstId::None);
     CARBON_CHECK(call_params_id == SemIR::InstBlockId::Empty ||
                  llvm::all_of(context.inst_blocks().Get(call_params_id),
                               [](SemIR::InstId inst_id) {
@@ -248,17 +248,17 @@ static auto PopImplIntroducerAndParamsAsNameComponent(
   }
 
   return {
-      .name_loc_id = Parse::NodeId::Invalid,
-      .name_id = SemIR::NameId::Invalid,
+      .name_loc_id = Parse::NodeId::None,
+      .name_id = SemIR::NameId::None,
       .first_param_node_id = first_param_node_id,
       .last_param_node_id = *last_param_iter,
       .implicit_params_loc_id = implicit_params_loc_id,
       .implicit_param_patterns_id =
-          implicit_param_patterns_id.value_or(SemIR::InstBlockId::Invalid),
-      .params_loc_id = Parse::NodeId::Invalid,
-      .param_patterns_id = SemIR::InstBlockId::Invalid,
-      .call_params_id = SemIR::InstBlockId::Invalid,
-      .return_slot_pattern_id = SemIR::InstId::Invalid,
+          implicit_param_patterns_id.value_or(SemIR::InstBlockId::None),
+      .params_loc_id = Parse::NodeId::None,
+      .param_patterns_id = SemIR::InstBlockId::None,
+      .call_params_id = SemIR::InstBlockId::None,
+      .return_slot_pattern_id = SemIR::InstId::None,
       .pattern_block_id = context.pattern_block_stack().Pop(),
   };
 }
@@ -270,7 +270,7 @@ static auto MergeImplRedecl(Context& context, SemIR::Impl& new_impl,
   // If the parameters aren't the same, then this is not a redeclaration of this
   // `impl`. Keep looking for a prior declaration without issuing a diagnostic.
   if (!CheckRedeclParamsMatch(context, DeclParams(new_impl),
-                              DeclParams(prev_impl), SemIR::SpecificId::Invalid,
+                              DeclParams(prev_impl), SemIR::SpecificId::None,
                               /*check_syntax=*/true, /*diagnose=*/false)) {
     // NOLINTNEXTLINE(readability-simplify-boolean-expr)
     return false;
@@ -360,7 +360,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
   // TODO: Check for an orphan `impl`.
 
   // Add the impl declaration.
-  SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::Invalid,
+  SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None,
                                .decl_block_id = decl_block_id};
   auto impl_decl_id =
       context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, impl_decl));
@@ -368,7 +368,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
   SemIR::Impl impl_info = {
       name_context.MakeEntityWithParamsBase(name, impl_decl_id,
                                             /*is_extern=*/false,
-                                            SemIR::LibraryNameId::Invalid),
+                                            SemIR::LibraryNameId::None),
       {.self_id = self_inst_id, .constraint_id = constraint_inst_id}};
 
   // Add the impl declaration.
@@ -388,7 +388,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
   }
 
   // Create a new impl if this isn't a valid redeclaration.
-  if (!impl_decl.impl_id.is_valid()) {
+  if (!impl_decl.impl_id.has_value()) {
     impl_info.generic_id = BuildGeneric(context, impl_decl_id);
     impl_info.witness_id = ImplWitnessForDeclaration(context, impl_info);
     AddConstantsToImplWitnessFromConstraint(
@@ -409,7 +409,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
   // For an `extend impl` declaration, mark the impl as extending this `impl`.
   if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
     auto extend_node = introducer.modifier_node_id(ModifierOrder::Decl);
-    if (impl_info.generic_id.is_valid()) {
+    if (impl_info.generic_id.has_value()) {
       SemIR::TypeId type_id = context.insts().Get(constraint_inst_id).type_id();
       constraint_inst_id = context.AddInst<SemIR::SpecificConstant>(
           context.insts().GetLocId(constraint_inst_id),
@@ -447,7 +447,7 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionStartId node_id)
   CARBON_CHECK(!impl_info.has_definition_started());
   impl_info.definition_id = impl_decl_id;
   impl_info.scope_id =
-      context.name_scopes().Add(impl_decl_id, SemIR::NameId::Invalid,
+      context.name_scopes().Add(impl_decl_id, SemIR::NameId::None,
                                 context.decl_name_stack().PeekParentScopeId());
 
   context.scope_stack().Push(

+ 11 - 12
toolchain/check/handle_interface.cpp

@@ -50,13 +50,13 @@ static auto BuildInterfaceDecl(Context& context,
   // Add the interface declaration.
   auto interface_decl =
       SemIR::InterfaceDecl{SemIR::TypeType::SingletonTypeId,
-                           SemIR::InterfaceId::Invalid, decl_block_id};
+                           SemIR::InterfaceId::None, decl_block_id};
   auto interface_decl_id =
       context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, interface_decl));
 
   SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase(
       name, interface_decl_id, /*is_extern=*/false,
-      SemIR::LibraryNameId::Invalid)};
+      SemIR::LibraryNameId::None)};
 
   // Check whether this is a redeclaration.
   auto [existing_id, is_poisoned] = context.decl_name_stack().LookupOrAddName(
@@ -64,7 +64,7 @@ static auto BuildInterfaceDecl(Context& context,
   if (is_poisoned) {
     // This is a declaration of a poisoned name.
     context.DiagnosePoisonedName(interface_decl_id);
-  } else if (existing_id.is_valid()) {
+  } else if (existing_id.has_value()) {
     if (auto existing_interface_decl =
             context.insts().Get(existing_id).TryAs<SemIR::InterfaceDecl>()) {
       auto existing_interface =
@@ -84,7 +84,7 @@ static auto BuildInterfaceDecl(Context& context,
             RedeclInfo(interface_info, node_id, is_definition),
             RedeclInfo(existing_interface, existing_interface.latest_decl_id(),
                        existing_interface.has_definition_started()),
-            /*prev_import_ir_id=*/SemIR::ImportIRId::Invalid);
+            /*prev_import_ir_id=*/SemIR::ImportIRId::None);
 
         // Can't merge interface definitions due to the generic requirements.
         if (!is_definition || !existing_interface.has_definition_started()) {
@@ -103,7 +103,7 @@ static auto BuildInterfaceDecl(Context& context,
   }
 
   // Create a new interface if this isn't a valid redeclaration.
-  if (!interface_decl.interface_id.is_valid()) {
+  if (!interface_decl.interface_id.has_value()) {
     // TODO: If this is an invalid redeclaration of a non-interface entity or
     // there was an error in the qualifier, we will have lost track of the
     // interface name here. We should keep track of it even if the name is
@@ -142,9 +142,8 @@ auto HandleParseNode(Context& context,
   CARBON_CHECK(!interface_info.has_definition_started(),
                "Can't merge with defined interfaces.");
   interface_info.definition_id = interface_decl_id;
-  interface_info.scope_id =
-      context.name_scopes().Add(interface_decl_id, SemIR::NameId::Invalid,
-                                interface_info.parent_scope_id);
+  interface_info.scope_id = context.name_scopes().Add(
+      interface_decl_id, SemIR::NameId::None, interface_info.parent_scope_id);
 
   auto self_specific_id =
       context.generics().GetSelfSpecific(interface_info.generic_id);
@@ -161,10 +160,10 @@ auto HandleParseNode(Context& context,
   SemIR::FacetType facet_type =
       context.FacetTypeFromInterface(interface_id, self_specific_id);
   SemIR::TypeId self_type_id = context.GetTypeIdForTypeConstant(
-      TryEvalInst(context, SemIR::InstId::Invalid, facet_type));
+      TryEvalInst(context, SemIR::InstId::None, facet_type));
 
   // We model `Self` as a symbolic binding whose type is the interface.
-  // Because there is no equivalent non-symbolic value, we use `Invalid` as
+  // Because there is no equivalent non-symbolic value, we use `None` as
   // the `value_id` on the `BindSymbolicName`.
   auto entity_name_id = context.entity_names().Add(
       {.name_id = SemIR::NameId::SelfType,
@@ -174,7 +173,7 @@ auto HandleParseNode(Context& context,
       context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
           {.type_id = self_type_id,
            .entity_name_id = entity_name_id,
-           .value_id = SemIR::InstId::Invalid}));
+           .value_id = SemIR::InstId::None}));
   context.scope_stack().PushCompileTimeBinding(interface_info.self_param_id);
   context.name_scopes().AddRequiredName(interface_info.scope_id,
                                         SemIR::NameId::SelfType,
@@ -206,7 +205,7 @@ auto HandleParseNode(Context& context, Parse::InterfaceDefinitionId /*node_id*/)
 
   // The interface type is now fully defined.
   auto& interface_info = context.interfaces().Get(interface_id);
-  if (!interface_info.associated_entities_id.is_valid()) {
+  if (!interface_info.associated_entities_id.has_value()) {
     interface_info.associated_entities_id = associated_entities_id;
   }
 

+ 4 - 4
toolchain/check/handle_let_and_var.cpp

@@ -57,7 +57,7 @@ static auto GetOrAddStorage(Context& context, SemIR::InstId pattern_id)
       context.insts().Get(pattern.inst.As<SemIR::VarPattern>().subpattern_id);
 
   // Try to populate name_id on a best-effort basis.
-  auto name_id = SemIR::NameId::Invalid;
+  auto name_id = SemIR::NameId::None;
   if (auto binding_pattern = subpattern.TryAs<SemIR::BindingPattern>()) {
     name_id =
         context.entity_names().Get(binding_pattern->entity_name_id).name_id;
@@ -69,7 +69,7 @@ static auto GetOrAddStorage(Context& context, SemIR::InstId pattern_id)
 
 auto HandleParseNode(Context& context, Parse::VariablePatternId node_id)
     -> bool {
-  auto subpattern_id = SemIR::InstId::Invalid;
+  auto subpattern_id = SemIR::InstId::None;
   if (context.node_stack().PeekIs(Parse::NodeKind::TuplePattern)) {
     context.node_stack().PopAndIgnore();
     CARBON_CHECK(
@@ -141,7 +141,7 @@ namespace {
 struct DeclInfo {
   // The optional initializer.
   std::optional<SemIR::InstId> init_id = std::nullopt;
-  SemIR::InstId pattern_id = SemIR::InstId::Invalid;
+  SemIR::InstId pattern_id = SemIR::InstId::None;
   std::optional<SemIR::Inst> parent_scope_inst = std::nullopt;
   DeclIntroducerState introducer = DeclIntroducerState();
 };
@@ -287,7 +287,7 @@ auto HandleParseNode(Context& context, Parse::VariableDeclId node_id) -> bool {
     return true;
   }
   LocalPatternMatch(context, decl_info->pattern_id,
-                    decl_info->init_id.value_or(SemIR::InstId::Invalid));
+                    decl_info->init_id.value_or(SemIR::InstId::None));
 
   return true;
 }

+ 4 - 4
toolchain/check/handle_modifier.cpp

@@ -60,23 +60,23 @@ static auto HandleModifier(Context& context, Parse::NodeId node_id,
     DiagnoseRepeated(context, current_modifier_node_id, node_id);
     return false;
   }
-  if (current_modifier_node_id.is_valid()) {
+  if (current_modifier_node_id.has_value()) {
     DiagnoseNotAllowedWith(context, current_modifier_node_id, node_id);
     return false;
   }
   if (auto later_modifier_set = s.modifier_set & later_modifiers;
       !later_modifier_set.empty()) {
     // At least one later modifier is present. Diagnose using the closest.
-    Parse::NodeId closest_later_modifier = Parse::NodeId::Invalid;
+    Parse::NodeId closest_later_modifier = Parse::NodeId::None;
     for (auto later_order = static_cast<int8_t>(order) + 1;
          later_order <= static_cast<int8_t>(ModifierOrder::Last);
          ++later_order) {
-      if (s.ordered_modifier_node_ids[later_order].is_valid()) {
+      if (s.ordered_modifier_node_ids[later_order].has_value()) {
         closest_later_modifier = s.ordered_modifier_node_ids[later_order];
         break;
       }
     }
-    CARBON_CHECK(closest_later_modifier.is_valid());
+    CARBON_CHECK(closest_later_modifier.has_value());
 
     CARBON_DIAGNOSTIC(ModifierMustAppearBefore, Error,
                       "`{0}` must appear before `{1}`", Lex::TokenKind,

+ 4 - 4
toolchain/check/handle_name.cpp

@@ -106,11 +106,11 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id,
   auto value = context.insts().Get(result.inst_id);
   auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
                                           value.type_id());
-  CARBON_CHECK(type_id.is_valid(), "Missing type for {0}", value);
+  CARBON_CHECK(type_id.has_value(), "Missing type for {0}", value);
 
   // If the named entity has a constant value that depends on its specific,
   // store the specific too.
-  if (result.specific_id.is_valid() &&
+  if (result.specific_id.has_value() &&
       context.constant_values().Get(result.inst_id).is_symbolic()) {
     result.inst_id = context.AddInst<SemIR::SpecificConstant>(
         node_id, {.type_id = type_id,
@@ -210,7 +210,7 @@ auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)
   } else {
     // Otherwise this is `.Member`, so look up `.Self` and then `Member` in
     // `.Self`.
-    SemIR::InstId period_self_id = SemIR::InstId::Invalid;
+    SemIR::InstId period_self_id = SemIR::InstId::None;
     {
       // TODO: Instead of annotating the diagnostic, should change
       // `HandleNameAsExpr` to optionally allow us to produce the diagnostic
@@ -222,7 +222,7 @@ auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)
             CARBON_DIAGNOSTIC(
                 NoPeriodSelfForDesignator, Note,
                 "designator may only be used when `.Self` is in scope");
-            builder.Note(SemIR::LocId::Invalid, NoPeriodSelfForDesignator);
+            builder.Note(SemIR::LocId::None, NoPeriodSelfForDesignator);
           });
       period_self_id =
           HandleNameAsExpr(context, node_id, SemIR::NameId::PeriodSelf);

+ 5 - 5
toolchain/check/handle_namespace.cpp

@@ -38,7 +38,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
 
   auto namespace_inst = SemIR::Namespace{
       context.GetSingletonType(SemIR::NamespaceType::SingletonInstId),
-      SemIR::NameScopeId::Invalid, SemIR::InstId::Invalid};
+      SemIR::NameScopeId::None, SemIR::InstId::None};
   auto namespace_id =
       context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, namespace_inst));
 
@@ -47,7 +47,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
                                                 SemIR::AccessKind::Public);
   if (is_poisoned) {
     context.DiagnosePoisonedName(namespace_id);
-  } else if (existing_inst_id.is_valid()) {
+  } else if (existing_inst_id.has_value()) {
     if (auto existing =
             context.insts().TryGetAs<SemIR::Namespace>(existing_inst_id)) {
       // If there's a name conflict with a namespace, "merge" by using the
@@ -67,8 +67,8 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
         context.name_scopes()
             .Get(existing->name_scope_id)
             .set_is_closed_import(false);
-      } else if (existing->import_id.is_valid() &&
-                 !context.insts().GetLocId(existing_inst_id).is_valid()) {
+      } else if (existing->import_id.has_value() &&
+                 !context.insts().GetLocId(existing_inst_id).has_value()) {
         // When the name conflict is an imported namespace, fill the location ID
         // so that future diagnostics point at this declaration.
         context.SetNamespaceNodeId(existing_inst_id, node_id);
@@ -81,7 +81,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
   // If we weren't able to merge namespaces, add a new name scope. Note this
   // occurs even for duplicates where we discard the namespace, because we want
   // to produce a valid constant.
-  if (!namespace_inst.name_scope_id.is_valid()) {
+  if (!namespace_inst.name_scope_id.has_value()) {
     namespace_inst.name_scope_id = context.name_scopes().Add(
         namespace_id, name_context.name_id_for_new_inst(),
         name_context.parent_scope_id);

+ 1 - 1
toolchain/check/handle_struct.cpp

@@ -108,7 +108,7 @@ static auto PopFieldNameNodes(Context& context, size_t field_count)
   while (true) {
     auto [name_node, _] =
         context.node_stack().PopWithNodeIdIf<Parse::NodeCategory::MemberName>();
-    if (name_node.is_valid()) {
+    if (name_node.has_value()) {
       nodes.push_back(name_node);
     } else {
       break;

+ 3 - 3
toolchain/check/handle_where.cpp

@@ -33,17 +33,17 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
       {.name_id = SemIR::NameId::PeriodSelf,
        .parent_scope_id = context.scope_stack().PeekNameScopeId(),
        // Invalid because this is not the parameter of a generic.
-       .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+       .bind_index = SemIR::CompileTimeBindIndex::None});
   auto inst_id =
       context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
           {.type_id = self_type_id,
            .entity_name_id = entity_name_id,
            // Invalid because there is no equivalent non-symbolic value.
-           .value_id = SemIR::InstId::Invalid}));
+           .value_id = SemIR::InstId::None}));
   auto existing =
       context.scope_stack().LookupOrAddName(SemIR::NameId::PeriodSelf, inst_id);
   // Shouldn't have any names in newly created scope.
-  CARBON_CHECK(!existing.is_valid());
+  CARBON_CHECK(!existing.has_value());
 
   // Save the `.Self` symbolic binding on the node stack. It will become the
   // first argument to the `WhereExpr` instruction.

+ 20 - 20
toolchain/check/impl.cpp

@@ -53,7 +53,7 @@ static auto GetSelfSpecificForInterfaceMemberWithSelfType(
   arg_ids.reserve(bindings.size());
 
   // Start with the enclosing arguments.
-  if (enclosing_specific_id.is_valid()) {
+  if (enclosing_specific_id.has_value()) {
     auto enclosing_specific_args_id =
         context.specifics().Get(enclosing_specific_id).args_id;
     auto enclosing_specific_args =
@@ -75,7 +75,7 @@ static auto GetSelfSpecificForInterfaceMemberWithSelfType(
   // since we haven't finished defining the implementation here.
   auto type_inst_id = context.types().GetInstId(self_type_id);
   auto facet_value_const_id =
-      TryEvalInst(context, SemIR::InstId::Invalid,
+      TryEvalInst(context, SemIR::InstId::None,
                   SemIR::FacetValue{.type_id = self_binding.type_id,
                                     .type_inst_id = type_inst_id,
                                     .witness_inst_id = witness_inst_id});
@@ -187,7 +187,7 @@ auto ImplWitnessForDeclaration(Context& context, const SemIR::Impl& impl)
   }
 
   llvm::SmallVector<SemIR::InstId> table(assoc_entities.size(),
-                                         SemIR::InstId::Invalid);
+                                         SemIR::InstId::None);
   auto table_id = context.inst_blocks().Add(table);
   return context.AddInst<SemIR::ImplWitness>(
       context.insts().GetLocId(impl.latest_decl_id()),
@@ -217,7 +217,7 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
                                              SemIR::ImplId prev_decl_id)
     -> void {
   CARBON_CHECK(!impl.has_definition_started());
-  CARBON_CHECK(witness_id.is_valid());
+  CARBON_CHECK(witness_id.has_value());
   if (witness_id == SemIR::ErrorInst::SingletonInstId) {
     return;
   }
@@ -240,8 +240,8 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
 
   // Scan through rewrites, produce map from element index to constant value.
   // TODO: Perhaps move this into facet type resolution?
-  llvm::SmallVector<SemIR::ConstantId> rewrite_values(
-      assoc_entities.size(), SemIR::ConstantId::Invalid);
+  llvm::SmallVector<SemIR::ConstantId> rewrite_values(assoc_entities.size(),
+                                                      SemIR::ConstantId::None);
   for (auto rewrite : facet_type_info.rewrite_constraints) {
     auto inst_id = context.constant_values().GetInstId(rewrite.lhs_const_id);
     auto access = context.insts().GetAs<SemIR::ImplWitnessAccess>(inst_id);
@@ -255,7 +255,7 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
     CARBON_CHECK(access.index.index <
                  static_cast<int32_t>(rewrite_values.size()));
     auto& rewrite_value = rewrite_values[access.index.index];
-    if (rewrite_value.is_valid() &&
+    if (rewrite_value.has_value() &&
         rewrite_value != SemIR::ErrorInst::SingletonConstantId) {
       if (rewrite_value != rewrite.rhs_const_id &&
           rewrite.rhs_const_id != SemIR::ErrorInst::SingletonConstantId) {
@@ -271,7 +271,7 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
         decl_id = context.constant_values().GetInstId(
             SemIR::GetConstantValueInSpecific(
                 context.sem_ir(), interface_type->specific_id, decl_id));
-        CARBON_CHECK(decl_id.is_valid(), "Non-constant associated entity");
+        CARBON_CHECK(decl_id.has_value(), "Non-constant associated entity");
         auto decl =
             context.insts().GetAs<SemIR::AssociatedConstantDecl>(decl_id);
         context.emitter().Emit(impl.constraint_id,
@@ -289,16 +289,16 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
     decl_id =
         context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
             context.sem_ir(), interface_type->specific_id, decl_id));
-    CARBON_CHECK(decl_id.is_valid(), "Non-constant associated entity");
+    CARBON_CHECK(decl_id.has_value(), "Non-constant associated entity");
     if (auto decl =
             context.insts().TryGetAs<SemIR::AssociatedConstantDecl>(decl_id)) {
       auto& witness_value = witness_block[index];
       auto rewrite_value = rewrite_values[index];
-      if (witness_value.is_valid() &&
+      if (witness_value.has_value() &&
           witness_value != SemIR::ErrorInst::SingletonInstId) {
         // TODO: Support just using the witness values if the redeclaration uses
         // `where _`, per proposal #1084.
-        if (!rewrite_value.is_valid()) {
+        if (!rewrite_value.has_value()) {
           CARBON_DIAGNOSTIC(AssociatedConstantMissingInRedecl, Error,
                             "associated constant {0} given value in "
                             "declaration but not redeclaration",
@@ -325,7 +325,7 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
           builder.Emit();
           continue;
         }
-      } else if (rewrite_value.is_valid()) {
+      } else if (rewrite_value.has_value()) {
         witness_value = context.constant_values().GetInstId(rewrite_value);
       }
     }
@@ -334,7 +334,7 @@ auto AddConstantsToImplWitnessFromConstraint(Context& context,
 
 auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void {
   CARBON_CHECK(impl.is_being_defined());
-  CARBON_CHECK(impl.witness_id.is_valid());
+  CARBON_CHECK(impl.witness_id.has_value());
   if (impl.witness_id == SemIR::ErrorInst::SingletonInstId) {
     return;
   }
@@ -363,11 +363,11 @@ auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void {
     decl_id =
         context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
             context.sem_ir(), interface_type->specific_id, decl_id));
-    CARBON_CHECK(decl_id.is_valid(), "Non-constant associated entity");
+    CARBON_CHECK(decl_id.has_value(), "Non-constant associated entity");
     if (auto decl =
             context.insts().TryGetAs<SemIR::AssociatedConstantDecl>(decl_id)) {
       auto& witness_value = witness_block[index];
-      if (!witness_value.is_valid()) {
+      if (!witness_value.has_value()) {
         CARBON_DIAGNOSTIC(ImplAssociatedConstantNeedsValue, Error,
                           "associated constant {0} not given a value in impl "
                           "of interface {1}",
@@ -391,7 +391,7 @@ auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void {
 // interface.
 auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void {
   CARBON_CHECK(impl.is_being_defined());
-  CARBON_CHECK(impl.witness_id.is_valid());
+  CARBON_CHECK(impl.witness_id.has_value());
   if (impl.witness_id == SemIR::ErrorInst::SingletonInstId) {
     return;
   }
@@ -420,7 +420,7 @@ auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void {
     decl_id =
         context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(
             context.sem_ir(), interface_type->specific_id, decl_id));
-    CARBON_CHECK(decl_id.is_valid(), "Non-constant associated entity");
+    CARBON_CHECK(decl_id.has_value(), "Non-constant associated entity");
     auto decl = context.insts().Get(decl_id);
     CARBON_KIND_SWITCH(decl) {
       case CARBON_KIND(SemIR::StructValue struct_value): {
@@ -436,7 +436,7 @@ auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void {
         auto& fn = context.functions().Get(fn_type->function_id);
         auto [impl_decl_id, _, is_poisoned] = context.LookupNameInExactScope(
             decl_id, fn.name_id, impl.scope_id, impl_scope);
-        if (impl_decl_id.is_valid()) {
+        if (impl_decl_id.has_value()) {
           used_decl_ids.push_back(impl_decl_id);
           witness_block[index] = CheckAssociatedFunctionImplementation(
               context, *fn_type, impl_decl_id, self_type_id, impl.witness_id);
@@ -471,12 +471,12 @@ auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void {
 }
 
 auto FillImplWitnessWithErrors(Context& context, SemIR::Impl& impl) -> void {
-  if (impl.witness_id.is_valid() &&
+  if (impl.witness_id.has_value() &&
       impl.witness_id != SemIR::ErrorInst::SingletonInstId) {
     auto witness = context.insts().GetAs<SemIR::ImplWitness>(impl.witness_id);
     auto witness_block = context.inst_blocks().GetMutable(witness.elements_id);
     for (auto& elem : witness_block) {
-      if (!elem.is_valid()) {
+      if (!elem.has_value()) {
         elem = SemIR::ErrorInst::SingletonInstId;
       }
     }

+ 12 - 12
toolchain/check/impl_lookup.cpp

@@ -23,11 +23,11 @@ static auto FindAssociatedImportIRs(Context& context,
     // We will look for impls in the import IR associated with the first owning
     // declaration.
     auto decl_id = entity.first_owning_decl_id;
-    if (!decl_id.is_valid()) {
+    if (!decl_id.has_value()) {
       return;
     }
     if (auto ir_id = GetCanonicalImportIRInst(context, decl_id).ir_id;
-        ir_id.is_valid()) {
+        ir_id.has_value()) {
       result.push_back(ir_id);
     }
   };
@@ -38,14 +38,14 @@ static auto FindAssociatedImportIRs(Context& context,
 
   // Push the contents of an instruction block onto our worklist.
   auto push_block = [&](SemIR::InstBlockId block_id) {
-    if (block_id.is_valid()) {
+    if (block_id.has_value()) {
       llvm::append_range(worklist, context.inst_blocks().Get(block_id));
     }
   };
 
   // Add the arguments of a specific to the worklist.
   auto push_args = [&](SemIR::SpecificId specific_id) {
-    if (specific_id.is_valid()) {
+    if (specific_id.has_value()) {
       push_block(context.specifics().Get(specific_id).args_id);
     }
   };
@@ -60,7 +60,7 @@ static auto FindAssociatedImportIRs(Context& context,
          {std::pair{inst.arg0(), arg0_kind}, {inst.arg1(), arg1_kind}}) {
       switch (kind) {
         case SemIR::IdKind::For<SemIR::InstId>: {
-          if (auto id = SemIR::InstId(arg); id.is_valid()) {
+          if (auto id = SemIR::InstId(arg); id.has_value()) {
             worklist.push_back(id);
           }
           break;
@@ -134,11 +134,11 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
   // considering impls that are for the same interface we're querying. We can
   // also skip impls that mention any types that aren't part of our impl query.
   for (const auto& impl : context.impls().array_ref()) {
-    auto specific_id = SemIR::SpecificId::Invalid;
-    if (impl.generic_id.is_valid()) {
+    auto specific_id = SemIR::SpecificId::None;
+    if (impl.generic_id.has_value()) {
       specific_id = DeduceImplArguments(context, loc_id, impl, type_const_id,
                                         interface_const_id);
-      if (!specific_id.is_valid()) {
+      if (!specific_id.has_value()) {
         continue;
       }
     }
@@ -156,12 +156,12 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
       // the constraint's interfaces.
       continue;
     }
-    if (!impl.witness_id.is_valid()) {
+    if (!impl.witness_id.has_value()) {
       // TODO: Diagnose if the impl isn't defined yet?
-      return SemIR::InstId::Invalid;
+      return SemIR::InstId::None;
     }
     LoadImportRef(context, impl.witness_id);
-    if (specific_id.is_valid()) {
+    if (specific_id.has_value()) {
       // We need a definition of the specific `impl` so we can access its
       // witness.
       ResolveSpecificDefinition(context, loc_id, specific_id);
@@ -170,7 +170,7 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
         SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id,
                                           impl.witness_id));
   }
-  return SemIR::InstId::Invalid;
+  return SemIR::InstId::None;
 }
 
 }  // namespace Carbon::Check

+ 1 - 1
toolchain/check/impl_lookup.h

@@ -11,7 +11,7 @@
 namespace Carbon::Check {
 
 // Looks up the witness to use for a particular type and interface. Returns the
-// witness, or `InstId::Invalid` if the type is not known to implement the
+// witness, or `InstId::None` if the type is not known to implement the
 // interface.
 auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
                        SemIR::ConstantId type_const_id,

+ 15 - 14
toolchain/check/import.cpp

@@ -78,7 +78,7 @@ static auto CopyNameFromImportIR(Context& context,
                                  const SemIR::File& import_sem_ir,
                                  SemIR::NameId import_name_id) {
   if (auto import_identifier_id = import_name_id.AsIdentifierId();
-      import_identifier_id.is_valid()) {
+      import_identifier_id.has_value()) {
     auto name = import_sem_ir.identifiers().Get(import_identifier_id);
     return SemIR::NameId::ForIdentifier(context.identifiers().Add(name));
   }
@@ -107,7 +107,7 @@ static auto AddNamespace(Context& context, SemIR::TypeId namespace_type_id,
   auto [inserted, entry_id] = parent_scope->LookupOrAdd(
       name_id,
       // This InstId is temporary and would be overridden if used.
-      SemIR::InstId::Invalid, SemIR::AccessKind::Public);
+      SemIR::InstId::None, SemIR::AccessKind::Public);
   if (!inserted) {
     const auto& prev_entry = parent_scope->GetEntry(entry_id);
     if (!prev_entry.is_poisoned) {
@@ -116,7 +116,7 @@ static auto AddNamespace(Context& context, SemIR::TypeId namespace_type_id,
               context.insts().TryGetAs<SemIR::Namespace>(prev_inst_id)) {
         if (diagnose_duplicate_namespace) {
           auto import_id = make_import_id();
-          CARBON_CHECK(import_id.is_valid());
+          CARBON_CHECK(import_id.has_value());
           context.DiagnoseDuplicateName(import_id, prev_inst_id);
         }
         return {namespace_inst->name_scope_id, prev_inst_id, true};
@@ -125,11 +125,11 @@ static auto AddNamespace(Context& context, SemIR::TypeId namespace_type_id,
   }
 
   auto import_id = make_import_id();
-  CARBON_CHECK(import_id.is_valid());
+  CARBON_CHECK(import_id.has_value());
   auto import_loc_id = context.insts().GetLocId(import_id);
 
-  auto namespace_inst = SemIR::Namespace{
-      namespace_type_id, SemIR::NameScopeId::Invalid, import_id};
+  auto namespace_inst =
+      SemIR::Namespace{namespace_type_id, SemIR::NameScopeId::None, import_id};
   auto namespace_inst_and_loc =
       import_loc_id.is_import_ir_inst_id()
           ? context.MakeImportedLocAndInst(import_loc_id.import_ir_inst_id(),
@@ -189,7 +189,7 @@ static auto CopySingleNameScopeFromImportIR(
     auto entity_name_id = context.entity_names().Add(
         {.name_id = name_id,
          .parent_scope_id = parent_scope_id,
-         .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+         .bind_index = SemIR::CompileTimeBindIndex::None});
     auto import_ir_inst_id = context.import_ir_insts().Add(
         {.ir_id = ir_id, .inst_id = import_inst_id});
     auto inst_id = context.AddInstInNoBlock(
@@ -277,13 +277,13 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id,
   auto [inserted, entry_id] = parent_scope.LookupOrAdd(
       name_id,
       // This InstId is temporary and would be overridden if used.
-      SemIR::InstId::Invalid, SemIR::AccessKind::Public);
+      SemIR::InstId::None, SemIR::AccessKind::Public);
   auto& entry = parent_scope.GetEntry(entry_id);
   if (inserted) {
     auto entity_name_id = context.entity_names().Add(
         {.name_id = name_id,
          .parent_scope_id = parent_scope_id,
-         .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+         .bind_index = SemIR::CompileTimeBindIndex::None});
     entry.inst_id = AddImportRef(
         context, {.ir_id = ir_id, .inst_id = import_inst_id}, entity_name_id);
     return;
@@ -321,7 +321,7 @@ static auto AddScopedImportRef(Context& context,
   auto impl_entity_name_id = context.entity_names().Add(
       {.name_id = name_id,
        .parent_scope_id = parent_scope_id,
-       .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+       .bind_index = SemIR::CompileTimeBindIndex::None});
   auto import_ref_id = AddImportRef(context, import_inst, impl_entity_name_id);
   parent_scope.AddRequired({.name_id = name_id,
                             .inst_id = import_ref_id,
@@ -484,7 +484,7 @@ static auto LookupNameInImport(const SemIR::File& import_ir,
   SemIR::NameId import_name_id = name_id;
   if (!identifier.empty()) {
     auto import_identifier_id = import_ir.identifiers().Lookup(identifier);
-    if (!import_identifier_id.is_valid()) {
+    if (!import_identifier_id.has_value()) {
       // Name doesn't exist in the import IR.
       return nullptr;
     }
@@ -538,7 +538,8 @@ auto ImportNameFromOtherPackage(
   // If the name is an identifier, get the string first so that it can be shared
   // when there are multiple IRs.
   llvm::StringRef identifier;
-  if (auto identifier_id = name_id.AsIdentifierId(); identifier_id.is_valid()) {
+  if (auto identifier_id = name_id.AsIdentifierId();
+      identifier_id.has_value()) {
     identifier = context.identifiers().Get(identifier_id);
     CARBON_CHECK(!identifier.empty());
   }
@@ -553,7 +554,7 @@ auto ImportNameFromOtherPackage(
 
   // Although we track the result here and look in each IR, we pretty much use
   // the first result.
-  auto result_id = SemIR::InstId::Invalid;
+  auto result_id = SemIR::InstId::None;
   // The canonical IR and inst_id for where `result_id` came from, which may be
   // indirectly imported. This is only resolved on a conflict, when it can be
   // used to determine the conflict is actually the same instruction.
@@ -576,7 +577,7 @@ auto ImportNameFromOtherPackage(
     }
 
     // Add the first result found.
-    if (!result_id.is_valid()) {
+    if (!result_id.has_value()) {
       // If the imported instruction is a namespace, we add it directly instead
       // of as an ImportRef.
       if (auto import_ns = import_inst.TryAs<SemIR::Namespace>()) {

+ 146 - 148
toolchain/check/import_ref.cpp

@@ -25,12 +25,12 @@ namespace Carbon::Check {
 static auto InternalAddImportIR(Context& context, SemIR::ImportIR import_ir)
     -> SemIR::ImportIRId {
   context.import_ir_constant_values().push_back(
-      SemIR::ConstantValueStore(SemIR::ConstantId::Invalid));
+      SemIR::ConstantValueStore(SemIR::ConstantId::None));
   return context.import_irs().Add(import_ir);
 }
 
 auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void {
-  auto ir_id = SemIR::ImportIRId::Invalid;
+  auto ir_id = SemIR::ImportIRId::None;
   if (import_ir.sem_ir != nullptr) {
     ir_id = AddImportIR(context, import_ir);
   } else {
@@ -44,7 +44,7 @@ auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void {
 auto AddImportIR(Context& context, SemIR::ImportIR import_ir)
     -> SemIR::ImportIRId {
   auto& ir_id = context.GetImportIRId(*import_ir.sem_ir);
-  if (!ir_id.is_valid()) {
+  if (!ir_id.has_value()) {
     // Note this updates check_ir_map.
     ir_id = InternalAddImportIR(context, import_ir);
   } else if (import_ir.is_export) {
@@ -57,7 +57,7 @@ auto AddImportIR(Context& context, SemIR::ImportIR import_ir)
 
 auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst,
                   SemIR::EntityNameId entity_name_id =
-                      SemIR::EntityNameId::Invalid) -> SemIR::InstId {
+                      SemIR::EntityNameId::None) -> SemIR::InstId {
   auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst);
   SemIR::ImportRefUnloaded inst = {.import_ir_inst_id = import_ir_inst_id,
                                    .entity_name_id = entity_name_id};
@@ -79,10 +79,9 @@ static auto AddLoadedImportRef(Context& context, SemIR::TypeId type_id,
                                SemIR::ImportIRInst import_ir_inst,
                                SemIR::ConstantId const_id) -> SemIR::InstId {
   auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst);
-  SemIR::ImportRefLoaded inst = {
-      .type_id = type_id,
-      .import_ir_inst_id = import_ir_inst_id,
-      .entity_name_id = SemIR::EntityNameId::Invalid};
+  SemIR::ImportRefLoaded inst = {.type_id = type_id,
+                                 .import_ir_inst_id = import_ir_inst_id,
+                                 .entity_name_id = SemIR::EntityNameId::None};
   auto inst_id = context.AddPlaceholderInstInNoBlock(
       context.MakeImportedLocAndInst(import_ir_inst_id, inst));
   context.import_ref_ids().push_back(inst_id);
@@ -120,11 +119,11 @@ static auto GetCanonicalImportIRInst(Context& context,
     break;
   }
 
-  auto ir_id = SemIR::ImportIRId::Invalid;
+  auto ir_id = SemIR::ImportIRId::None;
   if (cursor_ir != &context.sem_ir()) {
     // This uses AddImportIR in case it was indirectly found, which can
     // happen with two or more steps of exports.
-    ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::Invalid,
+    ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::None,
                                   .is_export = false,
                                   .sem_ir = cursor_ir});
   }
@@ -155,8 +154,8 @@ auto VerifySameCanonicalImportIRInst(Context& context, SemIR::InstId prev_id,
 static auto GetInstWithConstantValue(const SemIR::File& file,
                                      SemIR::ConstantId const_id)
     -> SemIR::InstId {
-  if (!const_id.is_valid()) {
-    return SemIR::InstId::Invalid;
+  if (!const_id.has_value()) {
+    return SemIR::InstId::None;
   }
 
   // For template constants, the corresponding instruction has the desired
@@ -169,7 +168,7 @@ static auto GetInstWithConstantValue(const SemIR::File& file,
   // desired constant value.
   const auto& symbolic_const =
       file.constant_values().GetSymbolicConstant(const_id);
-  if (!symbolic_const.generic_id.is_valid()) {
+  if (!symbolic_const.generic_id.has_value()) {
     return file.constant_values().GetInstId(const_id);
   }
 
@@ -188,7 +187,7 @@ struct ResolveResult {
   // The new constant value, if known.
   SemIR::ConstantId const_id;
   // Newly created declaration whose value is being resolved, if any.
-  SemIR::InstId decl_id = SemIR::InstId::Invalid;
+  SemIR::InstId decl_id = SemIR::InstId::None;
   // Whether resolution has been attempted once and needs to be retried.
   bool retry = false;
 
@@ -196,8 +195,8 @@ struct ResolveResult {
   // `const_id` is specified, then this is the end of the second phase, and the
   // constant value will be passed to the next resolution attempt. Otherwise,
   // this is the end of the first phase.
-  static auto Retry(SemIR::ConstantId const_id = SemIR::ConstantId::Invalid,
-                    SemIR::InstId decl_id = SemIR::InstId::Invalid)
+  static auto Retry(SemIR::ConstantId const_id = SemIR::ConstantId::None,
+                    SemIR::InstId decl_id = SemIR::InstId::None)
       -> ResolveResult {
     return {.const_id = const_id, .decl_id = decl_id, .retry = true};
   }
@@ -205,7 +204,7 @@ struct ResolveResult {
   // Produces a resolve result that provides the given constant value. Requires
   // that there is no new work.
   static auto Done(SemIR::ConstantId const_id,
-                   SemIR::InstId decl_id = SemIR::InstId::Invalid)
+                   SemIR::InstId decl_id = SemIR::InstId::None)
       -> ResolveResult {
     return {.const_id = const_id, .decl_id = decl_id};
   }
@@ -449,11 +448,11 @@ class ImportRefResolver : public ImportContext {
     work_stack_.push_back({.inst_id = inst_id});
     while (!work_stack_.empty()) {
       auto work = work_stack_.back();
-      CARBON_CHECK(work.inst_id.is_valid());
+      CARBON_CHECK(work.inst_id.has_value());
 
       // Step 1: check for a constant value.
       auto existing = FindResolvedConstId(work.inst_id);
-      if (existing.const_id.is_valid() && !work.retry_with_constant_value) {
+      if (existing.const_id.has_value() && !work.retry_with_constant_value) {
         work_stack_.pop_back();
         continue;
       }
@@ -465,22 +464,22 @@ class ImportRefResolver : public ImportContext {
       CARBON_CHECK(!HasNewWork() || retry);
 
       CARBON_CHECK(
-          !existing.const_id.is_valid() || existing.const_id == new_const_id,
+          !existing.const_id.has_value() || existing.const_id == new_const_id,
           "Constant value changed in third phase.");
-      if (!existing.const_id.is_valid()) {
+      if (!existing.const_id.has_value()) {
         SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id);
       }
 
       // Step 3: pop or retry.
       if (retry) {
         work_stack_[initial_work_ - 1].retry_with_constant_value =
-            new_const_id.is_valid();
+            new_const_id.has_value();
       } else {
         work_stack_.pop_back();
       }
     }
     auto constant_id = local_constant_values_for_import_insts().Get(inst_id);
-    CARBON_CHECK(constant_id.is_valid());
+    CARBON_CHECK(constant_id.has_value());
     return constant_id;
   }
 
@@ -499,13 +498,13 @@ class ImportRefResolver : public ImportContext {
 
   // Wraps constant evaluation with logic to handle types.
   auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId {
-    if (!import_type_id.is_valid()) {
+    if (!import_type_id.has_value()) {
       return import_type_id;
     }
 
     auto import_type_const_id =
         import_ir().types().GetConstantId(import_type_id);
-    CARBON_CHECK(import_type_const_id.is_valid());
+    CARBON_CHECK(import_type_const_id.has_value());
 
     if (auto import_type_inst_id =
             import_ir().constant_values().GetInstId(import_type_const_id);
@@ -530,7 +529,7 @@ class ImportRefResolver : public ImportContext {
   // work_stack_.
   auto GetLocalConstantValueOrPush(SemIR::InstId inst_id) -> SemIR::ConstantId {
     auto const_id = local_constant_values_for_import_insts().Get(inst_id);
-    if (!const_id.is_valid()) {
+    if (!const_id.has_value()) {
       work_stack_.push_back({.inst_id = inst_id});
     }
     return const_id;
@@ -549,7 +548,7 @@ class ImportRefResolver : public ImportContext {
   // The constant found by FindResolvedConstId.
   struct ResolvedConstId {
     // The constant for the instruction. Invalid if not yet resolved.
-    SemIR::ConstantId const_id = SemIR::ConstantId::Invalid;
+    SemIR::ConstantId const_id = SemIR::ConstantId::None;
 
     // Instructions which are indirect but equivalent to the current instruction
     // being resolved, and should have their constant set to the same. Empty
@@ -566,13 +565,13 @@ class ImportRefResolver : public ImportContext {
 
     if (auto existing_const_id =
             local_constant_values_for_import_insts().Get(inst_id);
-        existing_const_id.is_valid()) {
+        existing_const_id.has_value()) {
       result.const_id = existing_const_id;
       return result;
     }
 
     const auto* cursor_ir = &import_ir();
-    auto cursor_ir_id = SemIR::ImportIRId::Invalid;
+    auto cursor_ir_id = SemIR::ImportIRId::None;
     auto cursor_inst_id = inst_id;
 
     while (true) {
@@ -588,10 +587,10 @@ class ImportRefResolver : public ImportContext {
 
       cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id).sem_ir;
       cursor_ir_id = local_context().GetImportIRId(*cursor_ir);
-      if (!cursor_ir_id.is_valid()) {
+      if (!cursor_ir_id.has_value()) {
         // TODO: Should we figure out a location to assign here?
         cursor_ir_id =
-            AddImportIR(local_context(), {.decl_id = SemIR::InstId::Invalid,
+            AddImportIR(local_context(), {.decl_id = SemIR::InstId::None,
                                           .is_export = false,
                                           .sem_ir = cursor_ir});
       }
@@ -603,7 +602,7 @@ class ImportRefResolver : public ImportContext {
       if (auto const_id = local_context()
                               .import_ir_constant_values()[cursor_ir_id.index]
                               .Get(cursor_inst_id);
-          const_id.is_valid()) {
+          const_id.has_value()) {
         SetResolvedConstId(inst_id, result.indirect_insts, const_id);
         result.const_id = const_id;
         result.indirect_insts.clear();
@@ -637,7 +636,7 @@ class ImportRefResolver : public ImportContext {
 
 static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,
                          SemIR::EntityNameId entity_name_id =
-                             SemIR::EntityNameId::Invalid) -> SemIR::InstId {
+                             SemIR::EntityNameId::None) -> SemIR::InstId {
   return AddImportRef(context.local_context(),
                       {.ir_id = context.import_ir_id(), .inst_id = inst_id},
                       entity_name_id);
@@ -695,7 +694,7 @@ static auto GetLocalConstantIdChecked(ImportContext& context,
     -> SemIR::ConstantId {
   auto result_id =
       context.local_constant_values_for_import_insts().Get(inst_id);
-  CARBON_CHECK(result_id.is_valid());
+  CARBON_CHECK(result_id.has_value());
   return result_id;
 }
 
@@ -720,7 +719,7 @@ static auto GetLocalConstantIdChecked(ImportContext& context,
 // Translates a NameId from the import IR to a local NameId.
 static auto GetLocalNameId(ImportContext& context, SemIR::NameId import_name_id)
     -> SemIR::NameId {
-  if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.is_valid()) {
+  if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.has_value()) {
     return SemIR::NameId::ForIdentifier(context.local_identifiers().Add(
         context.import_identifiers().Get(ident_id)));
   }
@@ -732,7 +731,7 @@ static auto GetLocalInstBlockContents(ImportRefResolver& resolver,
                                       SemIR::InstBlockId import_block_id)
     -> llvm::SmallVector<SemIR::InstId> {
   llvm::SmallVector<SemIR::InstId> inst_ids;
-  if (!import_block_id.is_valid() ||
+  if (!import_block_id.has_value() ||
       import_block_id == SemIR::InstBlockId::Empty) {
     return inst_ids;
   }
@@ -756,8 +755,8 @@ static auto GetLocalCanonicalInstBlockId(ImportContext& context,
                                          SemIR::InstBlockId import_block_id,
                                          llvm::ArrayRef<SemIR::InstId> contents)
     -> SemIR::InstBlockId {
-  if (!import_block_id.is_valid()) {
-    return SemIR::InstBlockId::Invalid;
+  if (!import_block_id.has_value()) {
+    return SemIR::InstBlockId::None;
   }
   return context.local_inst_blocks().AddCanonical(contents);
 }
@@ -767,14 +766,14 @@ static auto GetLocalCanonicalInstBlockId(ImportContext& context,
 static auto MakeIncompleteGeneric(ImportContext& context, SemIR::InstId decl_id,
                                   SemIR::GenericId generic_id)
     -> SemIR::GenericId {
-  if (!generic_id.is_valid()) {
-    return SemIR::GenericId::Invalid;
+  if (!generic_id.has_value()) {
+    return SemIR::GenericId::None;
   }
 
   return context.local_generics().Add(
       {.decl_id = decl_id,
-       .bindings_id = SemIR::InstBlockId::Invalid,
-       .self_specific_id = SemIR::SpecificId::Invalid});
+       .bindings_id = SemIR::InstBlockId::None,
+       .self_specific_id = SemIR::SpecificId::None});
 }
 
 namespace {
@@ -787,7 +786,7 @@ struct GenericData {
 // Gets a local version of the data associated with a generic.
 static auto GetLocalGenericData(ImportRefResolver& resolver,
                                 SemIR::GenericId generic_id) -> GenericData {
-  if (!generic_id.is_valid()) {
+  if (!generic_id.has_value()) {
     return GenericData();
   }
 
@@ -800,7 +799,7 @@ static auto SetGenericData(ImportContext& context,
                            SemIR::GenericId import_generic_id,
                            SemIR::GenericId new_generic_id,
                            const GenericData& generic_data) -> void {
-  if (!import_generic_id.is_valid()) {
+  if (!import_generic_id.has_value()) {
     return;
   }
 
@@ -816,12 +815,12 @@ static auto SetGenericData(ImportContext& context,
 }
 
 // Gets a local constant value corresponding to an imported generic ID. May
-// add work to the work stack and return `Invalid`.
+// add work to the work stack and return `None`.
 static auto GetLocalConstantId(ImportRefResolver& resolver,
                                SemIR::GenericId generic_id)
     -> SemIR::ConstantId {
-  if (!generic_id.is_valid()) {
-    return SemIR::ConstantId::Invalid;
+  if (!generic_id.has_value()) {
+    return SemIR::ConstantId::None;
   }
   auto import_decl_inst_id = resolver.import_generics().Get(generic_id).decl_id;
   auto import_decl_inst = resolver.import_insts().Get(import_decl_inst_id);
@@ -840,8 +839,8 @@ static auto GetLocalConstantId(ImportRefResolver& resolver,
 static auto GetLocalGenericId(ImportContext& context,
                               SemIR::ConstantId local_const_id)
     -> SemIR::GenericId {
-  if (!local_const_id.is_valid()) {
-    return SemIR::GenericId::Invalid;
+  if (!local_const_id.has_value()) {
+    return SemIR::GenericId::None;
   }
   auto inst = context.local_insts().Get(
       context.local_constant_values().GetInstId(local_const_id));
@@ -878,8 +877,8 @@ struct SpecificData {
 static auto GetLocalSpecificData(ImportRefResolver& resolver,
                                  SemIR::SpecificId specific_id)
     -> SpecificData {
-  if (!specific_id.is_valid()) {
-    return {.generic_const_id = SemIR::ConstantId::Invalid, .args = {}};
+  if (!specific_id.has_value()) {
+    return {.generic_const_id = SemIR::ConstantId::None, .args = {}};
   }
 
   const auto& specific = resolver.import_specifics().Get(specific_id);
@@ -895,8 +894,8 @@ static auto GetOrAddLocalSpecific(ImportContext& context,
                                   SemIR::SpecificId import_specific_id,
                                   const SpecificData& data)
     -> SemIR::SpecificId {
-  if (!import_specific_id.is_valid()) {
-    return SemIR::SpecificId::Invalid;
+  if (!import_specific_id.has_value()) {
+    return SemIR::SpecificId::None;
   }
 
   // Form a corresponding local specific ID.
@@ -911,9 +910,9 @@ static auto GetOrAddLocalSpecific(ImportContext& context,
 
   // Fill in the remaining information in FinishPendingSpecific, if necessary.
   auto& specific = context.local_specifics().Get(specific_id);
-  if (!specific.decl_block_id.is_valid() ||
-      (import_specific.definition_block_id.is_valid() &&
-       !specific.definition_block_id.is_valid())) {
+  if (!specific.decl_block_id.has_value() ||
+      (import_specific.definition_block_id.has_value() &&
+       !specific.definition_block_id.has_value())) {
     context.AddPendingSpecific(
         {.import_id = import_specific_id, .local_id = specific_id});
   }
@@ -925,7 +924,7 @@ static auto GetOrAddLocalSpecific(ImportContext& context,
 static auto LoadLocalPatternConstantIds(ImportRefResolver& resolver,
                                         SemIR::InstBlockId param_patterns_id)
     -> void {
-  if (!param_patterns_id.is_valid() ||
+  if (!param_patterns_id.has_value() ||
       param_patterns_id == SemIR::InstBlockId::Empty) {
     return;
   }
@@ -968,7 +967,7 @@ static auto LoadLocalPatternConstantIds(ImportRefResolver& resolver,
 static auto GetLocalParamPatternsId(ImportContext& context,
                                     SemIR::InstBlockId param_patterns_id)
     -> SemIR::InstBlockId {
-  if (!param_patterns_id.is_valid() ||
+  if (!param_patterns_id.has_value() ||
       param_patterns_id == SemIR::InstBlockId::Empty) {
     return param_patterns_id;
   }
@@ -1000,13 +999,13 @@ static auto GetLocalParamPatternsId(ImportContext& context,
     auto type_id = context.local_context().GetTypeIdForTypeConstant(
         GetLocalConstantIdChecked(context, binding.type_id));
 
-    auto new_param_id = SemIR::InstId::Invalid;
+    auto new_param_id = SemIR::InstId::None;
     switch (binding.kind) {
       case SemIR::BindingPattern::Kind: {
         auto entity_name_id = context.local_entity_names().Add(
             {.name_id = name_id,
-             .parent_scope_id = SemIR::NameScopeId::Invalid,
-             .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+             .parent_scope_id = SemIR::NameScopeId::None,
+             .bind_index = SemIR::CompileTimeBindIndex::None});
         new_param_id =
             context.local_context().AddInstInNoBlock<SemIR::BindingPattern>(
                 AddImportIRInst(context, binding_id),
@@ -1055,8 +1054,8 @@ static auto GetLocalParamPatternsId(ImportContext& context,
 static auto GetLocalReturnSlotPatternId(
     ImportContext& context, SemIR::InstId import_return_slot_pattern_id)
     -> SemIR::InstId {
-  if (!import_return_slot_pattern_id.is_valid()) {
-    return SemIR::InstId::Invalid;
+  if (!import_return_slot_pattern_id.has_value()) {
+    return SemIR::InstId::None;
   }
 
   auto param_pattern = context.import_insts().GetAs<SemIR::OutParamPattern>(
@@ -1070,7 +1069,7 @@ static auto GetLocalReturnSlotPatternId(
   auto new_return_slot_pattern_id = context.local_context().AddInstInNoBlock(
       context.local_context().MakeImportedLocAndInst<SemIR::ReturnSlotPattern>(
           AddImportIRInst(context, param_pattern.subpattern_id),
-          {.type_id = type_id, .type_inst_id = SemIR::InstId::Invalid}));
+          {.type_id = type_id, .type_inst_id = SemIR::InstId::None}));
   return context.local_context().AddInstInNoBlock(
       context.local_context().MakeImportedLocAndInst<SemIR::OutParamPattern>(
           AddImportIRInst(context, import_return_slot_pattern_id),
@@ -1091,13 +1090,13 @@ static auto GetLocalNameScopeId(ImportRefResolver& resolver,
     // Map scopes that aren't associated with an instruction to invalid
     // scopes. For now, such scopes aren't used, and we don't have a good way
     // to remap them.
-    return SemIR::NameScopeId::Invalid;
+    return SemIR::NameScopeId::None;
   }
 
   // Get the constant value for the scope.
   auto const_id = GetLocalConstantId(resolver, inst_id);
-  if (!const_id.is_valid()) {
-    return SemIR::NameScopeId::Invalid;
+  if (!const_id.has_value()) {
+    return SemIR::NameScopeId::None;
   }
 
   auto const_inst_id = resolver.local_constant_values().GetInstId(const_id);
@@ -1141,7 +1140,7 @@ static auto GetLocalNameScopeId(ImportRefResolver& resolver,
     }
     default: {
       if (const_inst_id == SemIR::ErrorInst::SingletonInstId) {
-        return SemIR::NameScopeId::Invalid;
+        return SemIR::NameScopeId::None;
       }
       break;
     }
@@ -1162,8 +1161,8 @@ static auto GetIncompleteLocalEntityBase(
     const SemIR::EntityWithParamsBase& import_base)
     -> SemIR::EntityWithParamsBase {
   // Translate the extern_library_id if present.
-  auto extern_library_id = SemIR::LibraryNameId::Invalid;
-  if (import_base.extern_library_id.is_valid()) {
+  auto extern_library_id = SemIR::LibraryNameId::None;
+  if (import_base.extern_library_id.has_value()) {
     if (import_base.extern_library_id.index >= 0) {
       auto val = context.import_string_literal_values().Get(
           import_base.extern_library_id.AsStringLiteralValueId());
@@ -1176,28 +1175,28 @@ static auto GetIncompleteLocalEntityBase(
 
   return {
       .name_id = GetLocalNameId(context, import_base.name_id),
-      .parent_scope_id = SemIR::NameScopeId::Invalid,
+      .parent_scope_id = SemIR::NameScopeId::None,
       .generic_id =
           MakeIncompleteGeneric(context, decl_id, import_base.generic_id),
-      .first_param_node_id = Parse::NodeId::Invalid,
-      .last_param_node_id = Parse::NodeId::Invalid,
-      .pattern_block_id = SemIR::InstBlockId::Invalid,
+      .first_param_node_id = Parse::NodeId::None,
+      .last_param_node_id = Parse::NodeId::None,
+      .pattern_block_id = SemIR::InstBlockId::None,
       .implicit_param_patterns_id =
-          import_base.implicit_param_patterns_id.is_valid()
+          import_base.implicit_param_patterns_id.has_value()
               ? SemIR::InstBlockId::Empty
-              : SemIR::InstBlockId::Invalid,
-      .param_patterns_id = import_base.param_patterns_id.is_valid()
+              : SemIR::InstBlockId::None,
+      .param_patterns_id = import_base.param_patterns_id.has_value()
                                ? SemIR::InstBlockId::Empty
-                               : SemIR::InstBlockId::Invalid,
-      .call_params_id = SemIR::InstBlockId::Invalid,
+                               : SemIR::InstBlockId::None,
+      .call_params_id = SemIR::InstBlockId::None,
       .is_extern = import_base.is_extern,
       .extern_library_id = extern_library_id,
-      .non_owning_decl_id = import_base.non_owning_decl_id.is_valid()
+      .non_owning_decl_id = import_base.non_owning_decl_id.has_value()
                                 ? decl_id
-                                : SemIR::InstId::Invalid,
-      .first_owning_decl_id = import_base.first_owning_decl_id.is_valid()
+                                : SemIR::InstId::None,
+      .first_owning_decl_id = import_base.first_owning_decl_id.has_value()
                                   ? decl_id
-                                  : SemIR::InstId::Invalid,
+                                  : SemIR::InstId::None,
   };
 }
 
@@ -1235,7 +1234,7 @@ static auto AddAssociatedEntities(ImportContext& context,
   new_associated_entities.reserve(associated_entities.size());
   for (auto inst_id : associated_entities) {
     // Determine the name of the associated entity, by switching on its kind.
-    SemIR::NameId import_name_id = SemIR::NameId::Invalid;
+    SemIR::NameId import_name_id = SemIR::NameId::None;
     if (auto associated_const =
             context.import_insts().TryGetAs<SemIR::AssociatedConstantDecl>(
                 inst_id)) {
@@ -1259,7 +1258,7 @@ static auto AddAssociatedEntities(ImportContext& context,
     auto entity_name_id = context.local_entity_names().Add(
         {.name_id = name_id,
          .parent_scope_id = local_name_scope_id,
-         .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+         .bind_index = SemIR::CompileTimeBindIndex::None});
     new_associated_entities.push_back(
         AddImportRef(context, inst_id, entity_name_id));
   }
@@ -1283,8 +1282,7 @@ static auto RetryOrDone(ImportRefResolver& resolver, SemIR::ConstantId const_id)
 // that there is no new work.
 static auto ResolveAsUntyped(ImportContext& context, SemIR::Inst inst)
     -> ResolveResult {
-  auto result =
-      TryEvalInst(context.local_context(), SemIR::InstId::Invalid, inst);
+  auto result = TryEvalInst(context.local_context(), SemIR::InstId::None, inst);
   CARBON_CHECK(result.is_constant(), "{0} is not constant", inst);
   return ResolveResult::Done(result);
 }
@@ -1456,13 +1454,13 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   auto name_id = GetLocalNameId(resolver, import_entity_name.name_id);
   auto entity_name_id = resolver.local_entity_names().Add(
       {.name_id = name_id,
-       .parent_scope_id = SemIR::NameScopeId::Invalid,
+       .parent_scope_id = SemIR::NameScopeId::None,
        .bind_index = import_entity_name.bind_index});
   return ResolveAs<SemIR::BindSymbolicName>(
       resolver,
       {.type_id = resolver.local_context().GetTypeIdForTypeConstant(type_id),
        .entity_name_id = entity_name_id,
-       .value_id = SemIR::InstId::Invalid});
+       .value_id = SemIR::InstId::None});
 }
 
 static auto TryResolveTypedInst(ImportRefResolver& resolver,
@@ -1478,7 +1476,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   auto name_id = GetLocalNameId(resolver, import_entity_name.name_id);
   auto entity_name_id = resolver.local_entity_names().Add(
       {.name_id = name_id,
-       .parent_scope_id = SemIR::NameScopeId::Invalid,
+       .parent_scope_id = SemIR::NameScopeId::None,
        .bind_index = import_entity_name.bind_index});
   return ResolveAs<SemIR::SymbolicBindingPattern>(
       resolver,
@@ -1530,7 +1528,7 @@ static auto MakeIncompleteClass(ImportContext& context,
                                 SemIR::SpecificId enclosing_specific_id)
     -> std::pair<SemIR::ClassId, SemIR::ConstantId> {
   SemIR::ClassDecl class_decl = {.type_id = SemIR::TypeType::SingletonTypeId,
-                                 .class_id = SemIR::ClassId::Invalid,
+                                 .class_id = SemIR::ClassId::None,
                                  .decl_block_id = SemIR::InstBlockId::Empty};
   auto class_decl_id = context.local_context().AddPlaceholderInstInNoBlock(
       context.local_context().MakeImportedLocAndInst(
@@ -1539,7 +1537,7 @@ static auto MakeIncompleteClass(ImportContext& context,
   // incomplete type so that any references have something to point at.
   class_decl.class_id = context.local_classes().Add(
       {GetIncompleteLocalEntityBase(context, class_decl_id, import_class),
-       {.self_type_id = SemIR::TypeId::Invalid,
+       {.self_type_id = SemIR::TypeId::None,
         .inheritance_kind = import_class.inheritance_kind,
         .is_dynamic = import_class.is_dynamic}});
 
@@ -1567,7 +1565,7 @@ static auto AddClassDefinition(ImportContext& context,
   new_class.complete_type_witness_id = complete_type_witness_id;
 
   new_class.scope_id = context.local_name_scopes().Add(
-      new_class.first_owning_decl_id, SemIR::NameId::Invalid,
+      new_class.first_owning_decl_id, SemIR::NameId::None,
       new_class.parent_scope_id);
   auto& new_scope = context.local_name_scopes().Get(new_class.scope_id);
   const auto& import_scope =
@@ -1578,13 +1576,13 @@ static auto AddClassDefinition(ImportContext& context,
   AddNameScopeImportRefs(context, import_scope, new_scope);
   new_class.body_block_id = context.local_context().inst_block_stack().Pop();
 
-  if (import_class.base_id.is_valid()) {
+  if (import_class.base_id.has_value()) {
     new_class.base_id = base_id;
   }
-  if (import_class.adapt_id.is_valid()) {
+  if (import_class.adapt_id.has_value()) {
     new_class.adapt_id = adapt_id;
   }
-  if (import_class.vtable_id.is_valid()) {
+  if (import_class.vtable_id.has_value()) {
     new_class.vtable_id = vtable_id;
   }
 }
@@ -1598,9 +1596,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   // choice types. Factor out some of this functionality.
   const auto& import_class = resolver.import_classes().Get(inst.class_id);
 
-  SemIR::ClassId class_id = SemIR::ClassId::Invalid;
-  if (!class_const_id.is_valid()) {
-    auto import_specific_id = SemIR::SpecificId::Invalid;
+  SemIR::ClassId class_id = SemIR::ClassId::None;
+  if (!class_const_id.has_value()) {
+    auto import_specific_id = SemIR::SpecificId::None;
     if (auto import_generic_class_type =
             resolver.import_types().TryGetAs<SemIR::GenericClassType>(
                 inst.type_id)) {
@@ -1643,24 +1641,24 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   auto generic_data = GetLocalGenericData(resolver, import_class.generic_id);
   auto self_const_id = GetLocalConstantId(resolver, import_class.self_type_id);
   auto complete_type_witness_const_id =
-      import_class.complete_type_witness_id.is_valid()
+      import_class.complete_type_witness_id.has_value()
           ? GetLocalConstantId(resolver, import_class.complete_type_witness_id)
-          : SemIR::ConstantId::Invalid;
-  auto base_id = import_class.base_id.is_valid()
+          : SemIR::ConstantId::None;
+  auto base_id = import_class.base_id.has_value()
                      ? GetLocalConstantInstId(resolver, import_class.base_id)
-                     : SemIR::InstId::Invalid;
-  auto adapt_id = import_class.adapt_id.is_valid()
+                     : SemIR::InstId::None;
+  auto adapt_id = import_class.adapt_id.has_value()
                       ? GetLocalConstantInstId(resolver, import_class.adapt_id)
-                      : SemIR::InstId::Invalid;
+                      : SemIR::InstId::None;
   auto& new_class = resolver.local_classes().Get(class_id);
 
   if (resolver.HasNewWork()) {
     return ResolveResult::Retry(class_const_id, new_class.first_decl_id());
   }
 
-  auto vtable_id = import_class.vtable_id.is_valid()
+  auto vtable_id = import_class.vtable_id.has_value()
                        ? AddImportRef(resolver, import_class.vtable_id)
-                       : SemIR::InstId::Invalid;
+                       : SemIR::InstId::None;
 
   new_class.parent_scope_id = parent_scope_id;
   new_class.implicit_param_patterns_id = GetLocalParamPatternsId(
@@ -1778,8 +1776,8 @@ static auto MakeFunctionDecl(ImportContext& context,
                              SemIR::SpecificId specific_id)
     -> std::pair<SemIR::FunctionId, SemIR::ConstantId> {
   SemIR::FunctionDecl function_decl = {
-      .type_id = SemIR::TypeId::Invalid,
-      .function_id = SemIR::FunctionId::Invalid,
+      .type_id = SemIR::TypeId::None,
+      .function_id = SemIR::FunctionId::None,
       .decl_block_id = SemIR::InstBlockId::Empty};
   auto function_decl_id = context.local_context().AddPlaceholderInstInNoBlock(
       context.local_context().MakeImportedLocAndInst(
@@ -1789,7 +1787,7 @@ static auto MakeFunctionDecl(ImportContext& context,
   // Start with an incomplete function.
   function_decl.function_id = context.local_functions().Add(
       {GetIncompleteLocalEntityBase(context, function_decl_id, import_function),
-       {.return_slot_pattern_id = SemIR::InstId::Invalid,
+       {.return_slot_pattern_id = SemIR::InstId::None,
         .builtin_function_kind = import_function.builtin_function_kind}});
 
   function_decl.type_id = context.local_context().GetFunctionType(
@@ -1809,8 +1807,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   const auto& import_function =
       resolver.import_functions().Get(inst.function_id);
 
-  SemIR::FunctionId function_id = SemIR::FunctionId::Invalid;
-  if (!function_const_id.is_valid()) {
+  SemIR::FunctionId function_id = SemIR::FunctionId::None;
+  if (!function_const_id.has_value()) {
     auto import_specific_id = resolver.import_types()
                                   .GetAs<SemIR::FunctionType>(inst.type_id)
                                   .specific_id;
@@ -1836,8 +1834,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
     function_id = function_type.function_id;
   }
 
-  auto return_type_const_id = SemIR::ConstantId::Invalid;
-  if (import_function.return_slot_pattern_id.is_valid()) {
+  auto return_type_const_id = SemIR::ConstantId::None;
+  if (import_function.return_slot_pattern_id.has_value()) {
     return_type_const_id = GetLocalConstantId(
         resolver, resolver.import_insts()
                       .Get(import_function.return_slot_pattern_id)
@@ -1867,7 +1865,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   SetGenericData(resolver, import_function.generic_id, new_function.generic_id,
                  generic_data);
 
-  if (import_function.definition_id.is_valid()) {
+  if (import_function.definition_id.has_value()) {
     new_function.definition_id = new_function.first_owning_decl_id;
   }
 
@@ -1933,15 +1931,15 @@ static auto MakeImplDeclaration(ImportContext& context,
                                 const SemIR::Impl& import_impl,
                                 SemIR::InstId witness_id)
     -> std::pair<SemIR::ImplId, SemIR::ConstantId> {
-  SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::Invalid,
+  SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None,
                                .decl_block_id = SemIR::InstBlockId::Empty};
   auto impl_decl_id = context.local_context().AddPlaceholderInstInNoBlock(
       context.local_context().MakeImportedLocAndInst(
           AddImportIRInst(context, import_impl.latest_decl_id()), impl_decl));
   impl_decl.impl_id = context.local_impls().Add(
       {GetIncompleteLocalEntityBase(context, impl_decl_id, import_impl),
-       {.self_id = SemIR::InstId::Invalid,
-        .constraint_id = SemIR::InstId::Invalid,
+       {.self_id = SemIR::InstId::None,
+        .constraint_id = SemIR::InstId::None,
         .witness_id = witness_id}});
 
   // Write the impl ID into the ImplDecl.
@@ -1956,9 +1954,9 @@ static auto AddImplDefinition(ImportContext& context,
   new_impl.definition_id = new_impl.first_owning_decl_id;
   new_impl.defined = true;
 
-  if (import_impl.scope_id.is_valid()) {
+  if (import_impl.scope_id.has_value()) {
     new_impl.scope_id = context.local_name_scopes().Add(
-        new_impl.first_owning_decl_id, SemIR::NameId::Invalid,
+        new_impl.first_owning_decl_id, SemIR::NameId::None,
         new_impl.parent_scope_id);
     // Import the contents of the definition scope, if we might need it. Name
     // lookup is never performed into this scope by a user of the impl, so
@@ -1988,8 +1986,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   // functions. Factor out the commonality.
   const auto& import_impl = resolver.import_impls().Get(inst.impl_id);
 
-  SemIR::ImplId impl_id = SemIR::ImplId::Invalid;
-  if (!impl_const_id.is_valid()) {
+  SemIR::ImplId impl_id = SemIR::ImplId::None;
+  if (!impl_const_id.has_value()) {
     if (resolver.HasNewWork()) {
       // This is the end of the first phase. Don't make a new impl yet if we
       // already have new work.
@@ -2059,7 +2057,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
                                 SemIR::InstId inst_id) -> ResolveResult {
   // Return the constant for the instruction of the imported constant.
   auto constant_id = resolver.import_constant_values().Get(inst_id);
-  if (!constant_id.is_valid()) {
+  if (!constant_id.has_value()) {
     return ResolveResult::Done(SemIR::ErrorInst::SingletonConstantId);
   }
   if (!constant_id.is_constant()) {
@@ -2081,7 +2079,7 @@ static auto MakeInterfaceDecl(ImportContext& context,
     -> std::pair<SemIR::InterfaceId, SemIR::ConstantId> {
   SemIR::InterfaceDecl interface_decl = {
       .type_id = SemIR::TypeType::SingletonTypeId,
-      .interface_id = SemIR::InterfaceId::Invalid,
+      .interface_id = SemIR::InterfaceId::None,
       .decl_block_id = SemIR::InstBlockId::Empty};
   auto interface_decl_id = context.local_context().AddPlaceholderInstInNoBlock(
       context.local_context().MakeImportedLocAndInst(
@@ -2113,7 +2111,7 @@ static auto AddInterfaceDefinition(ImportContext& context,
                                    SemIR::Interface& new_interface,
                                    SemIR::InstId self_param_id) -> void {
   new_interface.scope_id = context.local_name_scopes().Add(
-      new_interface.first_owning_decl_id, SemIR::NameId::Invalid,
+      new_interface.first_owning_decl_id, SemIR::NameId::None,
       new_interface.parent_scope_id);
   auto& new_scope = context.local_name_scopes().Get(new_interface.scope_id);
   const auto& import_scope =
@@ -2139,9 +2137,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   const auto& import_interface =
       resolver.import_interfaces().Get(inst.interface_id);
 
-  SemIR::InterfaceId interface_id = SemIR::InterfaceId::Invalid;
-  if (!interface_const_id.is_valid()) {
-    auto import_specific_id = SemIR::SpecificId::Invalid;
+  SemIR::InterfaceId interface_id = SemIR::InterfaceId::None;
+  if (!interface_const_id.has_value()) {
+    auto import_specific_id = SemIR::SpecificId::None;
     if (auto import_generic_interface_type =
             resolver.import_types().TryGetAs<SemIR::GenericInterfaceType>(
                 inst.type_id)) {
@@ -2372,7 +2370,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
 
   // We can directly reuse the value IDs across file IRs. Otherwise, we need
   // to add a new canonical int in this IR.
-  auto int_id = inst.int_id.is_value()
+  auto int_id = inst.int_id.is_embedded_value()
                     ? inst.int_id
                     : resolver.local_ints().AddSigned(
                           resolver.import_ints().Get(inst.int_id));
@@ -2417,8 +2415,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
       SemIR::NamespaceType::SingletonInstId);
   auto namespace_decl =
       SemIR::Namespace{.type_id = namespace_type_id,
-                       .name_scope_id = SemIR::NameScopeId::Invalid,
-                       .import_id = SemIR::AbsoluteInstId::Invalid};
+                       .name_scope_id = SemIR::NameScopeId::None,
+                       .import_id = SemIR::AbsoluteInstId::None};
   auto inst_id = resolver.local_context().AddPlaceholderInstInNoBlock(
       resolver.local_context().MakeImportedLocAndInst(
           AddImportIRInst(resolver, import_inst_id), namespace_decl));
@@ -2607,7 +2605,7 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
                                     SemIR::ConstantId const_id)
     -> ResolveResult {
   if (SemIR::IsSingletonInstId(inst_id)) {
-    CARBON_CHECK(!const_id.is_valid());
+    CARBON_CHECK(!const_id.has_value());
     // Constants for builtins can be directly copied.
     return ResolveResult::Done(resolver.local_constant_values().Get(inst_id));
   }
@@ -2776,7 +2774,7 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
 static auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id,
                            SemIR::ConstantId const_id) -> ResolveResult {
   auto inst_const_id = resolver.import_constant_values().Get(inst_id);
-  if (!inst_const_id.is_valid() || !inst_const_id.is_symbolic()) {
+  if (!inst_const_id.has_value() || !inst_const_id.is_symbolic()) {
     return TryResolveInstCanonical(resolver, inst_id, const_id);
   }
 
@@ -2786,8 +2784,8 @@ static auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id,
   auto generic_const_id =
       GetLocalConstantId(resolver, symbolic_const.generic_id);
 
-  auto inner_const_id = SemIR::ConstantId::Invalid;
-  if (const_id.is_valid()) {
+  auto inner_const_id = SemIR::ConstantId::None;
+  if (const_id.has_value()) {
     // For the third phase, extract the constant value that
     // TryResolveInstCanonical produced previously.
     inner_const_id = resolver.local_constant_values().Get(
@@ -2796,21 +2794,21 @@ static auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id,
 
   // Import the constant and rebuild the symbolic constant data.
   auto result = TryResolveInstCanonical(resolver, inst_id, inner_const_id);
-  if (!result.const_id.is_valid()) {
+  if (!result.const_id.has_value()) {
     // First phase: TryResolveInstCanoncial needs a retry.
     return result;
   }
 
-  if (!const_id.is_valid()) {
+  if (!const_id.has_value()) {
     // Second phase: we have created an abstract constant. Create a
     // corresponding generic constant.
-    if (symbolic_const.generic_id.is_valid()) {
+    if (symbolic_const.generic_id.has_value()) {
       result.const_id = resolver.local_constant_values().AddSymbolicConstant(
           {.inst_id =
                resolver.local_constant_values().GetInstId(result.const_id),
            .generic_id = GetLocalGenericId(resolver, generic_const_id),
            .index = symbolic_const.index});
-      if (result.decl_id.is_valid()) {
+      if (result.decl_id.has_value()) {
         // Overwrite the abstract symbolic constant given initially to the
         // declaration with its final concrete symbolic value.
         resolver.local_constant_values().Set(result.decl_id, result.const_id);
@@ -2851,8 +2849,8 @@ static auto ResolveLocalEvalBlock(ImportRefResolver& resolver,
                                   SemIR::GenericInstIndex::Region region)
     -> SemIR::InstBlockId {
   auto import_block_id = import_generic.GetEvalBlock(region);
-  if (!import_block_id.is_valid()) {
-    return SemIR::InstBlockId::Invalid;
+  if (!import_block_id.has_value()) {
+    return SemIR::InstBlockId::None;
   }
 
   auto inst_ids = ResolveLocalInstBlockContents(resolver, import_block_id);
@@ -2895,8 +2893,8 @@ static auto FinishPendingGeneric(ImportRefResolver& resolver,
 static auto ResolveLocalInstBlock(ImportRefResolver& resolver,
                                   SemIR::InstBlockId import_block_id)
     -> SemIR::InstBlockId {
-  if (!import_block_id.is_valid()) {
-    return SemIR::InstBlockId::Invalid;
+  if (!import_block_id.has_value()) {
+    return SemIR::InstBlockId::None;
   }
 
   auto inst_ids = ResolveLocalInstBlockContents(resolver, import_block_id);
@@ -2915,7 +2913,7 @@ static auto FinishPendingSpecific(ImportRefResolver& resolver,
 
   if (!resolver.local_specifics()
            .Get(pending.local_id)
-           .decl_block_id.is_valid()) {
+           .decl_block_id.has_value()) {
     auto decl_block_id =
         ResolveLocalInstBlock(resolver, import_specific.decl_block_id);
     resolver.local_specifics().Get(pending.local_id).decl_block_id =
@@ -2924,8 +2922,8 @@ static auto FinishPendingSpecific(ImportRefResolver& resolver,
 
   if (!resolver.local_specifics()
            .Get(pending.local_id)
-           .definition_block_id.is_valid() &&
-      import_specific.definition_block_id.is_valid()) {
+           .definition_block_id.has_value() &&
+      import_specific.definition_block_id.has_value()) {
     auto definition_block_id =
         ResolveLocalInstBlock(resolver, import_specific.definition_block_id);
     resolver.local_specifics().Get(pending.local_id).definition_block_id =
@@ -2967,7 +2965,7 @@ static auto GetInstForLoad(Context& context,
                            SemIR::ImportIRInstId import_ir_inst_id)
     -> std::pair<llvm::SmallVector<SemIR::ImportIRInst>, SemIR::TypeId> {
   std::pair<llvm::SmallVector<SemIR::ImportIRInst>, SemIR::TypeId> result = {
-      {}, SemIR::TypeId::Invalid};
+      {}, SemIR::TypeId::None};
   auto& [import_ir_insts, type_id] = result;
 
   auto import_ir_inst = context.import_ir_insts().Get(import_ir_inst_id);
@@ -2989,7 +2987,7 @@ static auto GetInstForLoad(Context& context,
         cursor_ir->import_ir_insts().Get(import_ref->import_ir_inst_id);
     cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id).sem_ir;
     import_ir_insts.push_back(
-        {.ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::Invalid,
+        {.ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::None,
                                         .is_export = false,
                                         .sem_ir = cursor_ir}),
          .inst_id = import_ir_inst.inst_id});

+ 3 - 3
toolchain/check/inst_block_stack.cpp

@@ -28,7 +28,7 @@ auto InstBlockStack::PeekOrAdd(int depth) -> SemIR::InstBlockId {
   CARBON_CHECK(static_cast<int>(id_stack_.size()) > depth, "no such block");
   int index = id_stack_.size() - depth - 1;
   auto& slot = id_stack_[index];
-  if (!slot.is_valid()) {
+  if (!slot.has_value()) {
     slot = sem_ir_->inst_blocks().AddDefaultValue();
   }
   return slot;
@@ -41,7 +41,7 @@ auto InstBlockStack::Pop() -> SemIR::InstBlockId {
 
   // Finalize the block.
   if (!insts.empty() && id != SemIR::InstBlockId::Unreachable) {
-    if (id.is_valid()) {
+    if (id.has_value()) {
       sem_ir_->inst_blocks().Set(id, insts);
     } else {
       id = sem_ir_->inst_blocks().Add(insts);
@@ -51,7 +51,7 @@ auto InstBlockStack::Pop() -> SemIR::InstBlockId {
   insts_stack_.PopArray();
 
   CARBON_VLOG("{0} Pop {1}: {2}\n", name_, id_stack_.size(), id);
-  return id.is_valid() ? id : SemIR::InstBlockId::Empty;
+  return id.has_value() ? id : SemIR::InstBlockId::Empty;
 }
 
 auto InstBlockStack::PopAndDiscard() -> void {

+ 1 - 1
toolchain/check/inst_block_stack.h

@@ -33,7 +33,7 @@ class InstBlockStack {
 
   // Pushes a new instruction block. It will be invalid unless PeekOrAdd is
   // called in order to support lazy allocation.
-  auto Push() -> void { Push(SemIR::InstBlockId::Invalid); }
+  auto Push() -> void { Push(SemIR::InstBlockId::None); }
 
   // Pushes a new unreachable code block.
   auto PushUnreachable() -> void { Push(SemIR::InstBlockId::Unreachable); }

+ 12 - 12
toolchain/check/member_access.cpp

@@ -58,7 +58,7 @@ static auto GetHighestAllowedAccess(Context& context, SemIR::LocId loc_id,
   auto [_, self_type_inst_id, is_poisoned] = context.LookupUnqualifiedName(
       loc_id.node_id(), SemIR::NameId::SelfType, /*required=*/false);
   CARBON_CHECK(!is_poisoned);
-  if (!self_type_inst_id.is_valid()) {
+  if (!self_type_inst_id.has_value()) {
     return SemIR::AccessKind::Public;
   }
 
@@ -84,14 +84,14 @@ static auto GetHighestAllowedAccess(Context& context, SemIR::LocId loc_id,
     // accessing, try checking if this class is of the parent type of `Self`.
     if (auto base_type_id = self_class_info.GetBaseType(
             context.sem_ir(), self_class_type->specific_id);
-        base_type_id.is_valid()) {
+        base_type_id.has_value()) {
       if (context.types().GetConstantId(base_type_id) == name_scope_const_id) {
         return SemIR::AccessKind::Protected;
       }
       // TODO: Also check whether this base class has a base class of its own.
     } else if (auto adapt_type_id = self_class_info.GetAdaptedType(
                    context.sem_ir(), self_class_type->specific_id);
-               adapt_type_id.is_valid()) {
+               adapt_type_id.has_value()) {
       if (context.types().GetConstantId(adapt_type_id) == name_scope_const_id) {
         // TODO: Should we be allowed to access protected fields of a type we
         // are adapting? The design doesn't allow this.
@@ -110,7 +110,7 @@ static auto ScopeNeedsImplLookup(Context& context,
     -> bool {
   SemIR::InstId inst_id =
       context.constant_values().GetInstId(name_scope_const_id);
-  CARBON_CHECK(inst_id.is_valid());
+  CARBON_CHECK(inst_id.has_value());
   SemIR::Inst inst = context.insts().Get(inst_id);
 
   if (inst.Is<SemIR::FacetType>()) {
@@ -144,7 +144,7 @@ static auto AccessMemberOfImplWitness(Context& context, SemIR::LocId loc_id,
                                       SemIR::InstId member_id)
     -> SemIR::InstId {
   auto member_value_id = context.constant_values().GetConstantInstId(member_id);
-  if (!member_value_id.is_valid()) {
+  if (!member_value_id.has_value()) {
     if (member_value_id != SemIR::ErrorInst::SingletonInstId) {
       context.TODO(member_id, "non-constant associated entity");
     }
@@ -189,7 +189,7 @@ static auto PerformImplLookup(
   auto witness_id =
       LookupImplWitness(context, loc_id, type_const_id,
                         assoc_type.interface_type_id.AsConstantId());
-  if (!witness_id.is_valid()) {
+  if (!witness_id.has_value()) {
     auto interface_type_id = context.GetInterfaceType(
         interface_type->interface_id, interface_type->specific_id);
     if (missing_impl_diagnoser) {
@@ -237,7 +237,7 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
       context.LookupQualifiedName(loc_id, name_id, lookup_scopes,
                                   /*required=*/true, access_info);
 
-  if (!result.inst_id.is_valid()) {
+  if (!result.inst_id.has_value()) {
     return SemIR::ErrorInst::SingletonInstId;
   }
 
@@ -245,11 +245,11 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
   auto inst = context.insts().Get(result.inst_id);
   auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id,
                                           inst.type_id());
-  CARBON_CHECK(type_id.is_valid(), "Missing type for member {0}", inst);
+  CARBON_CHECK(type_id.has_value(), "Missing type for member {0}", inst);
 
   // If the named entity has a constant value that depends on its specific,
   // store the specific too.
-  if (result.specific_id.is_valid() &&
+  if (result.specific_id.has_value() &&
       context.constant_values().Get(result.inst_id).is_symbolic()) {
     result.inst_id = context.GetOrAddInst<SemIR::SpecificConstant>(
         loc_id, {.type_id = type_id,
@@ -290,7 +290,7 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
         const auto& facet_type_info =
             context.facet_types().Get(facet_type.facet_type_id);
         // Witness that `T` implements the `*assoc_interface`.
-        SemIR::InstId witness_inst_id = SemIR::InstId::Invalid;
+        SemIR::InstId witness_inst_id = SemIR::InstId::None;
         for (auto base_interface : facet_type_info.impls_constraints) {
           // Get the witness that `T` implements `base_type_id`.
           if (base_interface == *assoc_interface) {
@@ -308,7 +308,7 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,
         }
         // TODO: If that fails, would need to do impl lookup to see if the facet
         // value implements the interface of `*assoc_type`.
-        if (!witness_inst_id.is_valid()) {
+        if (!witness_inst_id.has_value()) {
           context.TODO(member_id,
                        "associated entity not found in facet type, need to do "
                        "impl lookup");
@@ -353,7 +353,7 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id,
       // Find the specified element, which could be either a field or a base
       // class, and build an element access expression.
       auto element_id = context.constant_values().GetConstantInstId(member_id);
-      CARBON_CHECK(element_id.is_valid(),
+      CARBON_CHECK(element_id.has_value(),
                    "Non-constant value {0} of unbound element type",
                    context.insts().Get(member_id));
       auto index = GetClassElementIndex(context, element_id);

+ 17 - 17
toolchain/check/merge.cpp

@@ -95,7 +95,7 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
                              SemIR::NameId name_id, RedeclInfo new_decl,
                              RedeclInfo prev_decl,
                              SemIR::ImportIRId import_ir_id) -> void {
-  if (!import_ir_id.is_valid()) {
+  if (!import_ir_id.has_value()) {
     // Check for disallowed redeclarations in the same file.
     if (!new_decl.is_definition) {
       DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc,
@@ -146,8 +146,8 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
                            prev_decl.loc);
     return;
   }
-  if (!prev_decl.extern_library_id.is_valid()) {
-    if (new_decl.extern_library_id.is_valid()) {
+  if (!prev_decl.extern_library_id.has_value()) {
+    if (new_decl.extern_library_id.has_value()) {
       DiagnoseExternLibraryInImporter(context, decl_kind, name_id, new_decl.loc,
                                       prev_decl.loc);
     } else {
@@ -179,7 +179,7 @@ static auto EntityHasParamError(Context& context, const DeclParams& info)
     -> bool {
   for (auto param_patterns_id :
        {info.implicit_param_patterns_id, info.param_patterns_id}) {
-    if (param_patterns_id.is_valid() &&
+    if (param_patterns_id.has_value() &&
         param_patterns_id != SemIR::InstBlockId::Empty) {
       for (auto param_id : context.inst_blocks().Get(param_patterns_id)) {
         if (context.insts().Get(param_id).type_id() ==
@@ -293,7 +293,7 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
   }
 
   // If exactly one of the parameter lists was present, they differ.
-  if (new_param_patterns_id.is_valid() != prev_param_patterns_id.is_valid()) {
+  if (new_param_patterns_id.has_value() != prev_param_patterns_id.has_value()) {
     if (!diagnose) {
       return false;
     }
@@ -307,15 +307,15 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc,
                       BoolAsSelect, BoolAsSelect);
     context.emitter()
         .Build(new_decl_loc, RedeclParamListDiffers, is_implicit_param,
-               new_param_patterns_id.is_valid())
+               new_param_patterns_id.has_value())
         .Note(prev_decl_loc, RedeclParamListPrevious, is_implicit_param,
-              prev_param_patterns_id.is_valid())
+              prev_param_patterns_id.has_value())
         .Emit();
     return false;
   }
 
-  CARBON_CHECK(new_param_patterns_id.is_valid() &&
-               prev_param_patterns_id.is_valid());
+  CARBON_CHECK(new_param_patterns_id.has_value() &&
+               prev_param_patterns_id.has_value());
   const auto new_param_pattern_ids =
       context.inst_blocks().Get(new_param_patterns_id);
   const auto prev_param_pattern_ids =
@@ -382,16 +382,16 @@ static auto CheckRedeclParamSyntax(Context& context,
   // TODO: Support cross-file syntax checks. Right now imports provide invalid
   // nodes, and we'll need to follow the declaration to its original file to
   // get the parse tree.
-  if (!new_first_param_node_id.is_valid() ||
-      !prev_first_param_node_id.is_valid()) {
+  if (!new_first_param_node_id.has_value() ||
+      !prev_first_param_node_id.has_value()) {
     return true;
   }
-  CARBON_CHECK(new_last_param_node_id.is_valid(),
-               "new_last_param_node_id.is_valid should match "
-               "new_first_param_node_id.is_valid");
-  CARBON_CHECK(prev_last_param_node_id.is_valid(),
-               "prev_last_param_node_id.is_valid should match "
-               "prev_first_param_node_id.is_valid");
+  CARBON_CHECK(new_last_param_node_id.has_value(),
+               "new_last_param_node_id.has_value should match "
+               "new_first_param_node_id.has_value");
+  CARBON_CHECK(prev_last_param_node_id.has_value(),
+               "prev_last_param_node_id.has_value should match "
+               "prev_first_param_node_id.has_value");
   Parse::Tree::PostorderIterator new_iter(new_first_param_node_id);
   Parse::Tree::PostorderIterator new_end(new_last_param_node_id);
   Parse::Tree::PostorderIterator prev_iter(prev_first_param_node_id);

+ 1 - 1
toolchain/check/merge.h

@@ -99,7 +99,7 @@ struct DeclParams {
 auto CheckRedeclParamsMatch(
     Context& context, const DeclParams& new_entity,
     const DeclParams& prev_entity,
-    SemIR::SpecificId prev_specific_id = SemIR::SpecificId::Invalid,
+    SemIR::SpecificId prev_specific_id = SemIR::SpecificId::None,
     bool check_syntax = true, bool diagnose = true) -> bool;
 
 }  // namespace Carbon::Check

+ 5 - 5
toolchain/check/modifiers.cpp

@@ -39,7 +39,7 @@ static auto DiagnoseNotAllowed(
     SemIR::LocId context_loc_id) -> void {
   auto diag = StartDiagnoseNotAllowed(context, diagnostic_base, modifier_node,
                                       decl_kind);
-  if (context_loc_id.is_valid()) {
+  if (context_loc_id.has_value()) {
     CARBON_DIAGNOSTIC(ModifierNotInContext, Note, "containing definition here");
     diag.Note(context_loc_id, ModifierNotInContext);
   }
@@ -67,7 +67,7 @@ template <typename DiagnosticBaseT>
 static auto ForbidModifiersOnDecl(
     Context& context, const DiagnosticBaseT& diagnostic_base,
     DeclIntroducerState& introducer, KeywordModifierSet forbidden,
-    SemIR::LocId context_loc_id = SemIR::LocId::Invalid) -> void {
+    SemIR::LocId context_loc_id = SemIR::LocId::None) -> void {
   auto not_allowed = introducer.modifier_set & forbidden;
   if (not_allowed.empty()) {
     return;
@@ -80,7 +80,7 @@ static auto ForbidModifiersOnDecl(
       DiagnoseNotAllowed(context, diagnostic_base,
                          introducer.modifier_node_id(order), introducer.kind,
                          context_loc_id);
-      introducer.set_modifier_node_id(order, Parse::NodeId::Invalid);
+      introducer.set_modifier_node_id(order, Parse::NodeId::None);
     }
   }
 
@@ -189,7 +189,7 @@ auto RestrictExternModifierOnDecl(Context& context,
     ForbidModifiersOnDecl(context, ModifierExternNotAllowed, introducer,
                           KeywordModifierSet::Extern);
     // Treat as unset.
-    introducer.extern_library = SemIR::LibraryNameId::Invalid;
+    introducer.extern_library = SemIR::LibraryNameId::None;
     return;
   }
 
@@ -204,7 +204,7 @@ auto RestrictExternModifierOnDecl(Context& context,
     // Right now this can produce both this and the below diagnostic.
   }
 
-  if (is_definition && introducer.extern_library.is_valid()) {
+  if (is_definition && introducer.extern_library.has_value()) {
     CARBON_DIAGNOSTIC(ExternLibraryOnDefinition, Error,
                       "a library cannot be provided for an `extern` modifier "
                       "on a definition");

+ 12 - 11
toolchain/check/name_component.cpp

@@ -11,8 +11,8 @@ namespace Carbon::Check {
 
 auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
     -> NameComponent {
-  Parse::NodeId first_param_node_id = Parse::InvalidNodeId();
-  Parse::NodeId last_param_node_id = Parse::InvalidNodeId();
+  Parse::NodeId first_param_node_id = Parse::NoneNodeId();
+  Parse::NodeId last_param_node_id = Parse::NoneNodeId();
 
   // Explicit params.
   auto [params_loc_id, param_patterns_id] =
@@ -23,7 +23,7 @@ auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
             .PopForSoloNodeId<Parse::NodeKind::TuplePatternStart>();
     last_param_node_id = params_loc_id;
   } else {
-    param_patterns_id = SemIR::InstBlockId::Invalid;
+    param_patterns_id = SemIR::InstBlockId::None;
   }
 
   // Implicit params.
@@ -36,16 +36,17 @@ auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
         context.node_stack()
             .PopForSoloNodeId<Parse::NodeKind::ImplicitParamListStart>();
     // Only use the end of implicit params if there weren't explicit params.
-    if (last_param_node_id.is_valid()) {
+    if (last_param_node_id.has_value()) {
       last_param_node_id = params_loc_id;
     }
   } else {
-    implicit_param_patterns_id = SemIR::InstBlockId::Invalid;
+    implicit_param_patterns_id = SemIR::InstBlockId::None;
   }
 
-  auto call_params_id = SemIR::InstBlockId::Invalid;
-  auto pattern_block_id = SemIR::InstBlockId::Invalid;
-  if (param_patterns_id->is_valid() || implicit_param_patterns_id->is_valid()) {
+  auto call_params_id = SemIR::InstBlockId::None;
+  auto pattern_block_id = SemIR::InstBlockId::None;
+  if (param_patterns_id->has_value() ||
+      implicit_param_patterns_id->has_value()) {
     call_params_id =
         CalleePatternMatch(context, *implicit_param_patterns_id,
                            *param_patterns_id, return_slot_pattern_id);
@@ -77,17 +78,17 @@ auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
 auto PopNameComponentWithoutParams(Context& context, Lex::TokenKind introducer)
     -> NameComponent {
   NameComponent name = PopNameComponent(context);
-  if (name.call_params_id.is_valid()) {
+  if (name.call_params_id.has_value()) {
     CARBON_DIAGNOSTIC(UnexpectedDeclNameParams, Error,
                       "`{0}` declaration cannot have parameters",
                       Lex::TokenKind);
     // Point to the lexically first parameter list in the diagnostic.
-    context.emitter().Emit(name.implicit_param_patterns_id.is_valid()
+    context.emitter().Emit(name.implicit_param_patterns_id.has_value()
                                ? name.implicit_params_loc_id
                                : name.params_loc_id,
                            UnexpectedDeclNameParams, introducer);
 
-    name.call_params_id = SemIR::InstBlockId::Invalid;
+    name.call_params_id = SemIR::InstBlockId::None;
   }
   return name;
 }

+ 1 - 1
toolchain/check/name_component.h

@@ -52,7 +52,7 @@ struct NameComponent {
 // Pops a name component from the node stack (and pattern block stack, if it has
 // parameters).
 auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id =
-                                            SemIR::InstId::Invalid)
+                                            SemIR::InstId::None)
     -> NameComponent;
 
 // Equivalent to PopNameComponent, but also diagnoses if the name component has

+ 4 - 5
toolchain/check/node_id_traversal.cpp

@@ -14,10 +14,9 @@ NodeIdTraversal::NodeIdTraversal(Context& context,
       next_deferred_definition_(&context.parse_tree()),
       worklist_(vlog_stream) {
   auto range = context.parse_tree().postorder();
-  chunks_.push_back(
-      {.it = range.begin(),
-       .end = range.end(),
-       .next_definition = Parse::DeferredDefinitionIndex::Invalid});
+  chunks_.push_back({.it = range.begin(),
+                     .end = range.end(),
+                     .next_definition = Parse::DeferredDefinitionIndex::None});
 }
 
 auto NodeIdTraversal::Next() -> std::optional<Parse::NodeId> {
@@ -166,7 +165,7 @@ auto NodeIdTraversal::NextDeferredDefinitionCache::SkipTo(
   index_ = next_index;
   if (static_cast<size_t>(index_.index) ==
       tree_->deferred_definitions().size()) {
-    start_id_ = Parse::NodeId::Invalid;
+    start_id_ = Parse::NodeId::None;
   } else {
     start_id_ = tree_->deferred_definitions().Get(index_).start_id;
   }

+ 2 - 2
toolchain/check/node_id_traversal.h

@@ -46,8 +46,8 @@ class NodeIdTraversal {
    private:
     const Parse::Tree* tree_;
     Parse::DeferredDefinitionIndex index_ =
-        Parse::DeferredDefinitionIndex::Invalid;
-    Parse::NodeId start_id_ = Parse::NodeId::Invalid;
+        Parse::DeferredDefinitionIndex::None;
+    Parse::NodeId start_id_ = Parse::NodeId::None;
   };
 
   // A chunk of the parse tree that we need to type-check.

+ 5 - 5
toolchain/check/node_stack.h

@@ -20,7 +20,7 @@ namespace Carbon::Check {
 class IdUnion {
  public:
   // The default constructor forms an invalid ID.
-  explicit constexpr IdUnion() : index(AnyIdBase::InvalidIndex) {}
+  explicit constexpr IdUnion() : index(AnyIdBase::NoneIndex) {}
 
   template <typename IdT>
     requires SemIR::IdKind::Contains<IdT>
@@ -41,7 +41,7 @@ class IdUnion {
     return As<SemIR::IdKind::TypeFor<K>>();
   }
 
-  // Translates an ID type to the enum ID kind. Returns Invalid if `IdT` isn't
+  // Translates an ID type to the enum ID kind. Returns `None` if `IdT` isn't
   // a type that can be stored in this union.
   template <typename IdT>
   static constexpr auto KindFor() -> Kind {
@@ -92,7 +92,7 @@ class NodeStack {
     auto kind = parse_tree_->node_kind(node_id);
     CARBON_CHECK(NodeKindToIdKind(kind) == Id::KindFor<IdT>(),
                  "Parse kind expected a different IdT: {0} -> {1}\n", kind, id);
-    CARBON_CHECK(id.is_valid(), "Push called with invalid id: {0}",
+    CARBON_CHECK(id.has_value(), "Push called with `None` id: {0}",
                  parse_tree_->node_kind(node_id));
     CARBON_VLOG("Node Push {0}: {1} -> {2}\n", stack_.size(), kind, id);
     CARBON_CHECK(stack_.size() < (1 << 20),
@@ -271,7 +271,7 @@ class NodeStack {
   auto PopWithNodeIdIf() -> std::pair<Parse::NodeIdForKind<RequiredParseKind>,
                                       decltype(PopIf<RequiredParseKind>())> {
     if (!PeekIs(RequiredParseKind)) {
-      return {Parse::NodeId::Invalid, std::nullopt};
+      return {Parse::NodeId::None, std::nullopt};
     }
     return PopWithNodeId<RequiredParseKind>();
   }
@@ -283,7 +283,7 @@ class NodeStack {
       -> std::pair<Parse::NodeIdInCategory<RequiredParseCategory>,
                    decltype(PopIf<RequiredParseCategory>())> {
     if (!PeekIs(RequiredParseCategory)) {
-      return {Parse::NodeId::Invalid, std::nullopt};
+      return {Parse::NodeId::None, std::nullopt};
     }
     return PopWithNodeId<RequiredParseCategory>();
   }

+ 25 - 25
toolchain/check/pattern_match.cpp

@@ -29,7 +29,7 @@ static auto GetPrettyName(Context& context, ParamPattern param_pattern)
           param_pattern.subpattern_id)) {
     return context.entity_names().Get(binding_pattern->entity_name_id).name_id;
   }
-  return SemIR::NameId::Invalid;
+  return SemIR::NameId::None;
 }
 
 namespace {
@@ -64,7 +64,7 @@ class MatchContext {
   // match operation is part of implementing the signature of the given
   // specific.
   explicit MatchContext(MatchKind kind, SemIR::SpecificId callee_specific_id =
-                                            SemIR::SpecificId::Invalid)
+                                            SemIR::SpecificId::None)
       : next_index_(0), kind_(kind), callee_specific_id_(callee_specific_id) {}
 
   // Adds a work item to the stack.
@@ -147,8 +147,8 @@ auto MatchContext::EmitPatternMatch(Context& context,
       // to avoid accidentally consuming it twice.
       auto [bind_name_id, type_expr_region_id] = std::exchange(
           context.bind_name_map().Lookup(entry.pattern_id).value(),
-          {.bind_name_id = SemIR::InstId::Invalid,
-           .type_expr_region_id = SemIR::ExprRegionId::Invalid});
+          {.bind_name_id = SemIR::InstId::None,
+           .type_expr_region_id = SemIR::ExprRegionId::None});
       context.InsertHere(type_expr_region_id);
       auto value_id = entry.scrutinee_id;
       switch (kind_) {
@@ -161,7 +161,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
         case MatchKind::Callee: {
           if (context.insts()
                   .GetAs<SemIR::AnyParam>(value_id)
-                  .runtime_index.is_valid()) {
+                  .runtime_index.has_value()) {
             results_.push_back(value_id);
           }
           break;
@@ -170,7 +170,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
           CARBON_FATAL("Found binding pattern during caller pattern match");
       }
       auto bind_name = context.insts().GetAs<SemIR::AnyBindName>(bind_name_id);
-      CARBON_CHECK(!bind_name.value_id.is_valid());
+      CARBON_CHECK(!bind_name.value_id.has_value());
       bind_name.value_id = value_id;
       context.ReplaceInstBeforeConstantUse(bind_name_id, bind_name);
       context.inst_block_stack().AddInstId(bind_name_id);
@@ -183,10 +183,10 @@ auto MatchContext::EmitPatternMatch(Context& context,
         // the caller side of the pattern, so we traverse without emitting any
         // insts.
         AddWork({.pattern_id = addr_pattern.inner_id,
-                 .scrutinee_id = SemIR::InstId::Invalid});
+                 .scrutinee_id = SemIR::InstId::None});
         break;
       }
-      CARBON_CHECK(entry.scrutinee_id.is_valid());
+      CARBON_CHECK(entry.scrutinee_id.has_value());
       auto scrutinee_ref_id =
           ConvertToValueOrRefExpr(context, entry.scrutinee_id);
       switch (SemIR::GetExprCategory(context.sem_ir(), scrutinee_ref_id)) {
@@ -220,7 +220,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
                    results_.size(), param_pattern.runtime_index.index);
       switch (kind_) {
         case MatchKind::Caller: {
-          CARBON_CHECK(entry.scrutinee_id.is_valid());
+          CARBON_CHECK(entry.scrutinee_id.has_value());
           if (entry.scrutinee_id == SemIR::ErrorInst::SingletonInstId) {
             results_.push_back(SemIR::ErrorInst::SingletonInstId);
           } else {
@@ -259,7 +259,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
     case CARBON_KIND(SemIR::OutParamPattern param_pattern): {
       switch (kind_) {
         case MatchKind::Caller: {
-          CARBON_CHECK(entry.scrutinee_id.is_valid());
+          CARBON_CHECK(entry.scrutinee_id.has_value());
           CARBON_CHECK(context.insts().Get(entry.scrutinee_id).type_id() ==
                        SemIR::GetTypeInSpecific(context.sem_ir(),
                                                 callee_specific_id_,
@@ -302,7 +302,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
       bool already_in_lookup =
           context.scope_stack()
               .LookupOrAddName(SemIR::NameId::ReturnSlot, return_slot_id)
-              .is_valid();
+              .has_value();
       CARBON_CHECK(!already_in_lookup);
       results_.push_back(entry.scrutinee_id);
       break;
@@ -315,7 +315,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
       if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
         context.global_init().Resume();
       }
-      if (entry.scrutinee_id.is_valid()) {
+      if (entry.scrutinee_id.has_value()) {
         auto init_id =
             Initialize(context, pattern.loc_id, var_id, entry.scrutinee_id);
         // TODO: Consider using different instruction kinds for assignment
@@ -341,33 +341,33 @@ auto CalleePatternMatch(Context& context,
                         SemIR::InstBlockId param_patterns_id,
                         SemIR::InstId return_slot_pattern_id)
     -> SemIR::InstBlockId {
-  if (!return_slot_pattern_id.is_valid() && !param_patterns_id.is_valid() &&
-      !implicit_param_patterns_id.is_valid()) {
-    return SemIR::InstBlockId::Invalid;
+  if (!return_slot_pattern_id.has_value() && !param_patterns_id.has_value() &&
+      !implicit_param_patterns_id.has_value()) {
+    return SemIR::InstBlockId::None;
   }
 
   MatchContext match(MatchKind::Callee);
 
   // We add work to the stack in reverse so that the results will be produced
   // in the original order.
-  if (return_slot_pattern_id.is_valid()) {
+  if (return_slot_pattern_id.has_value()) {
     match.AddWork({.pattern_id = return_slot_pattern_id,
-                   .scrutinee_id = SemIR::InstId::Invalid});
+                   .scrutinee_id = SemIR::InstId::None});
   }
 
-  if (param_patterns_id.is_valid()) {
+  if (param_patterns_id.has_value()) {
     for (SemIR::InstId inst_id :
          llvm::reverse(context.inst_blocks().Get(param_patterns_id))) {
       match.AddWork(
-          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::Invalid});
+          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
     }
   }
 
-  if (implicit_param_patterns_id.is_valid()) {
+  if (implicit_param_patterns_id.has_value()) {
     for (SemIR::InstId inst_id :
          llvm::reverse(context.inst_blocks().Get(implicit_param_patterns_id))) {
       match.AddWork(
-          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::Invalid});
+          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
     }
   }
 
@@ -385,8 +385,8 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
   MatchContext match(MatchKind::Caller, specific_id);
 
   // Track the return storage, if present.
-  if (return_slot_arg_id.is_valid()) {
-    CARBON_CHECK(return_slot_pattern_id.is_valid());
+  if (return_slot_arg_id.has_value()) {
+    CARBON_CHECK(return_slot_pattern_id.has_value());
     match.AddWork({.pattern_id = return_slot_pattern_id,
                    .scrutinee_id = return_slot_arg_id});
   }
@@ -397,7 +397,7 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
     auto runtime_index = SemIR::Function::GetParamPatternInfoFromPatternId(
                              context.sem_ir(), param_pattern_id)
                              .inst.runtime_index;
-    if (!runtime_index.is_valid()) {
+    if (!runtime_index.has_value()) {
       // Not a runtime parameter: we don't pass an argument.
       continue;
     }
@@ -405,7 +405,7 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
     match.AddWork({.pattern_id = param_pattern_id, .scrutinee_id = arg_id});
   }
 
-  if (self_pattern_id.is_valid()) {
+  if (self_pattern_id.has_value()) {
     match.AddWork({.pattern_id = self_pattern_id, .scrutinee_id = self_arg_id});
   }
 

+ 9 - 9
toolchain/check/return.cpp

@@ -80,7 +80,7 @@ auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,
   }
 
   // A `returned var` requires an explicit return type.
-  if (!return_info.type_id.is_valid()) {
+  if (!return_info.type_id.has_value()) {
     CARBON_DIAGNOSTIC(ReturnedVarWithNoReturnType, Error,
                       "cannot declare a `returned var` in this function");
     auto diag =
@@ -103,7 +103,7 @@ auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,
   }
 
   auto existing_id = context.scope_stack().SetReturnedVarOrGetExisting(bind_id);
-  if (existing_id.is_valid()) {
+  if (existing_id.has_value()) {
     CARBON_DIAGNOSTIC(ReturnedVarShadowed, Error,
                       "cannot declare a `returned var` in the scope of "
                       "another `returned var`");
@@ -118,7 +118,7 @@ auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id)
   const auto& function = GetCurrentFunctionForReturn(context);
   auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());
 
-  if (return_type_id.is_valid()) {
+  if (return_type_id.has_value()) {
     CARBON_DIAGNOSTIC(ReturnStatementMissingExpr, Error,
                       "missing return value");
     auto diag = context.emitter().Build(node_id, ReturnStatementMissingExpr);
@@ -133,11 +133,11 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id,
                          SemIR::InstId expr_id) -> void {
   const auto& function = GetCurrentFunctionForReturn(context);
   auto returned_var_id = GetCurrentReturnedVar(context);
-  auto return_slot_id = SemIR::InstId::Invalid;
+  auto return_slot_id = SemIR::InstId::None;
   auto return_info =
       SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(), function);
 
-  if (!return_info.type_id.is_valid()) {
+  if (!return_info.type_id.has_value()) {
     CARBON_DIAGNOSTIC(
         ReturnStatementDisallowExpr, Error,
         "no return expression should be provided in this context");
@@ -145,7 +145,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id,
     NoteNoReturnTypeProvided(diag, function);
     diag.Emit();
     expr_id = SemIR::ErrorInst::SingletonInstId;
-  } else if (returned_var_id.is_valid()) {
+  } else if (returned_var_id.has_value()) {
     CARBON_DIAGNOSTIC(
         ReturnExprWithReturnedVar, Error,
         "can only `return var;` in the scope of a `returned var`");
@@ -159,7 +159,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id,
     expr_id = SemIR::ErrorInst::SingletonInstId;
   } else if (return_info.has_return_slot()) {
     return_slot_id = GetCurrentReturnSlot(context);
-    CARBON_CHECK(return_slot_id.is_valid());
+    CARBON_CHECK(return_slot_id.has_value());
     // Note that this can import a function and invalidate `function`.
     expr_id = Initialize(context, node_id, return_slot_id, expr_id);
   } else {
@@ -176,7 +176,7 @@ auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)
   const auto& function = GetCurrentFunctionForReturn(context);
   auto returned_var_id = GetCurrentReturnedVar(context);
 
-  if (!returned_var_id.is_valid()) {
+  if (!returned_var_id.has_value()) {
     CARBON_DIAGNOSTIC(ReturnVarWithNoReturnedVar, Error,
                       "`return var;` with no `returned var` in scope");
     context.emitter().Emit(node_id, ReturnVarWithNoReturnedVar);
@@ -189,7 +189,7 @@ auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)
     // If we don't have a return slot, we're returning by value. Convert to a
     // value expression.
     returned_var_id = ConvertToValueExpr(context, returned_var_id);
-    return_slot_id = SemIR::InstId::Invalid;
+    return_slot_id = SemIR::InstId::None;
   }
 
   context.AddInst<SemIR::ReturnExpr>(

+ 2 - 2
toolchain/check/scope_index.h

@@ -20,13 +20,13 @@ namespace Carbon::Check {
 struct ScopeIndex : public IndexBase<ScopeIndex> {
   static constexpr llvm::StringLiteral Label = "scope";
   static const ScopeIndex Package;
-  static const ScopeIndex Invalid;
+  static const ScopeIndex None;
 
   using IndexBase::IndexBase;
 };
 
 constexpr ScopeIndex ScopeIndex::Package = ScopeIndex(0);
-constexpr ScopeIndex ScopeIndex::Invalid = ScopeIndex(InvalidIndex);
+constexpr ScopeIndex ScopeIndex::None = ScopeIndex(NoneIndex);
 
 }  // namespace Carbon::Check
 

+ 16 - 16
toolchain/check/scope_stack.cpp

@@ -31,7 +31,7 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
   // If this scope doesn't have a specific of its own, it lives in the enclosing
   // scope's specific, if any.
   auto enclosing_specific_id = specific_id;
-  if (!specific_id.is_valid() && !scope_stack_.empty()) {
+  if (!specific_id.has_value() && !scope_stack_.empty()) {
     enclosing_specific_id = PeekSpecificId();
   }
 
@@ -45,7 +45,7 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
            compile_time_binding_stack_.all_values_size()),
        .lexical_lookup_has_load_error =
            LexicalLookupHasLoadError() || lexical_lookup_has_load_error});
-  if (scope_id.is_valid()) {
+  if (scope_id.has_value()) {
     non_lexical_scope_stack_.push_back({.scope_index = next_scope_index_,
                                         .name_scope_id = scope_id,
                                         .specific_id = enclosing_specific_id});
@@ -53,7 +53,7 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
     // For lexical lookups, unqualified lookup doesn't know how to find the
     // associated specific, so if we start adding lexical scopes associated with
     // specifics, we'll need to somehow track them in lookup.
-    CARBON_CHECK(!specific_id.is_valid(),
+    CARBON_CHECK(!specific_id.has_value(),
                  "Lexical scope should not have an associated specific.");
   }
 
@@ -75,15 +75,15 @@ auto ScopeStack::Pop() -> void {
     lexical_results.pop_back();
   });
 
-  if (scope.scope_id.is_valid()) {
+  if (scope.scope_id.has_value()) {
     CARBON_CHECK(non_lexical_scope_stack_.back().scope_index == scope.index);
     non_lexical_scope_stack_.pop_back();
   }
 
   if (scope.has_returned_var) {
     CARBON_CHECK(!return_scope_stack_.empty());
-    CARBON_CHECK(return_scope_stack_.back().returned_var.is_valid());
-    return_scope_stack_.back().returned_var = SemIR::InstId::Invalid;
+    CARBON_CHECK(return_scope_stack_.back().returned_var.has_value());
+    return_scope_stack_.back().returned_var = SemIR::InstId::None;
   }
 
   VerifyNextCompileTimeBindIndex("Pop", scope);
@@ -104,12 +104,12 @@ auto ScopeStack::LookupInLexicalScopesWithin(SemIR::NameId name_id,
     -> SemIR::InstId {
   auto& lexical_results = lexical_lookup_.Get(name_id);
   if (lexical_results.empty()) {
-    return SemIR::InstId::Invalid;
+    return SemIR::InstId::None;
   }
 
   auto result = lexical_results.back();
   if (result.scope_index < scope_index) {
-    return SemIR::InstId::Invalid;
+    return SemIR::InstId::None;
   }
 
   return result.inst_id;
@@ -125,7 +125,7 @@ auto ScopeStack::LookupInLexicalScopes(SemIR::NameId name_id)
   // If we have no lexical results, check all non-lexical scopes.
   if (lexical_results.empty()) {
     return {LexicalLookupHasLoadError() ? SemIR::ErrorInst::SingletonInstId
-                                        : SemIR::InstId::Invalid,
+                                        : SemIR::InstId::None,
             non_lexical_scope_stack_};
   }
 
@@ -150,7 +150,7 @@ auto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,
   // function, so it should be relatively rare, but it's still not necesasry to
   // recompute this.
   int scope_depth = scope_stack_.size() - 1;
-  if (scope_index.is_valid()) {
+  if (scope_index.has_value()) {
     scope_depth =
         std::lower_bound(scope_stack_.begin(), scope_stack_.end(), scope_index,
                          [](const ScopeStackEntry& entry, ScopeIndex index) {
@@ -178,31 +178,31 @@ auto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,
 
   // Add a corresponding lexical lookup result.
   lexical_results.push_back({.inst_id = target_id, .scope_index = scope_index});
-  return SemIR::InstId::Invalid;
+  return SemIR::InstId::None;
 }
 
 auto ScopeStack::SetReturnedVarOrGetExisting(SemIR::InstId inst_id)
     -> SemIR::InstId {
   CARBON_CHECK(!return_scope_stack_.empty(), "`returned var` in no function");
   auto& returned_var = return_scope_stack_.back().returned_var;
-  if (returned_var.is_valid()) {
+  if (returned_var.has_value()) {
     return returned_var;
   }
 
   returned_var = inst_id;
   CARBON_CHECK(!scope_stack_.back().has_returned_var,
                "Scope has returned var but none is set");
-  if (inst_id.is_valid()) {
+  if (inst_id.has_value()) {
     scope_stack_.back().has_returned_var = true;
   }
-  return SemIR::InstId::Invalid;
+  return SemIR::InstId::None;
 }
 
 auto ScopeStack::Suspend() -> SuspendedScope {
   CARBON_CHECK(!scope_stack_.empty(), "No scope to suspend");
   SuspendedScope result = {.entry = scope_stack_.pop_back_val(),
                            .suspended_items = {}};
-  if (result.entry.scope_id.is_valid()) {
+  if (result.entry.scope_id.has_value()) {
     non_lexical_scope_stack_.pop_back();
   }
 
@@ -246,7 +246,7 @@ auto ScopeStack::Restore(SuspendedScope scope) -> void {
 
   VerifyNextCompileTimeBindIndex("Restore", scope.entry);
 
-  if (scope.entry.scope_id.is_valid()) {
+  if (scope.entry.scope_id.has_value()) {
     non_lexical_scope_stack_.push_back(
         {.scope_index = scope.entry.index,
          .name_scope_id = scope.entry.scope_id,

+ 7 - 7
toolchain/check/scope_stack.h

@@ -37,7 +37,7 @@ class ScopeStack {
 
     // The value corresponding to the current `returned var`, if any. Will be
     // set and unset as `returned var`s are declared and go out of scope.
-    SemIR::InstId returned_var = SemIR::InstId::Invalid;
+    SemIR::InstId returned_var = SemIR::InstId::None;
   };
 
   // A non-lexical scope in which unqualified lookup may be required.
@@ -55,13 +55,13 @@ class ScopeStack {
   // Information about a scope that has been temporarily removed from the stack.
   struct SuspendedScope;
 
-  // Pushes a scope onto scope_stack_. NameScopeId::Invalid is used for new
+  // Pushes a scope onto scope_stack_. NameScopeId::None is used for new
   // scopes. lexical_lookup_has_load_error is used to limit diagnostics when a
   // given namespace may contain a mix of both successful and failed name
   // imports.
-  auto Push(SemIR::InstId scope_inst_id = SemIR::InstId::Invalid,
-            SemIR::NameScopeId scope_id = SemIR::NameScopeId::Invalid,
-            SemIR::SpecificId specific_id = SemIR::SpecificId::Invalid,
+  auto Push(SemIR::InstId scope_inst_id = SemIR::InstId::None,
+            SemIR::NameScopeId scope_id = SemIR::NameScopeId::None,
+            SemIR::SpecificId specific_id = SemIR::SpecificId::None,
             bool lexical_lookup_has_load_error = false) -> void;
 
   // Pops the top scope from scope_stack_, cleaning up names from
@@ -101,7 +101,7 @@ class ScopeStack {
   template <typename InstT>
   auto GetCurrentScopeAs(const SemIR::File& sem_ir) -> std::optional<InstT> {
     auto inst_id = PeekInstId();
-    if (!inst_id.is_valid()) {
+    if (!inst_id.has_value()) {
       return std::nullopt;
     }
     return sem_ir.insts().TryGetAs<InstT>(inst_id);
@@ -129,7 +129,7 @@ class ScopeStack {
   // in that scope or any unfinished scope within it, and otherwise adds the
   // name with the value `target_id` and returns Invalid.
   auto LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,
-                       ScopeIndex scope_index = ScopeIndex::Invalid)
+                       ScopeIndex scope_index = ScopeIndex::None)
       -> SemIR::InstId;
 
   // Prepares to add a compile-time binding in the current scope, and returns

+ 13 - 13
toolchain/check/sem_ir_diagnostic_converter.cpp

@@ -16,7 +16,7 @@ auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc,
 
   // Use the token when possible, but -1 is the default value.
   auto last_offset = -1;
-  if (last_token_.is_valid()) {
+  if (last_token_.has_value()) {
     last_offset = sem_ir_->parse_tree().tokens().GetByteOffset(last_token_);
   }
 
@@ -37,14 +37,14 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
     -> ConvertedDiagnosticLoc {
   // Cursors for the current IR and instruction in that IR.
   const auto* cursor_ir = sem_ir_;
-  auto cursor_inst_id = SemIR::InstId::Invalid;
+  auto cursor_inst_id = SemIR::InstId::None;
 
   // Notes an import on the diagnostic and updates cursors to point at the
   // imported IR.
   auto follow_import_ref = [&](SemIR::ImportIRInstId import_ir_inst_id) {
     auto import_ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id);
     const auto& import_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id);
-    CARBON_CHECK(import_ir.decl_id.is_valid(),
+    CARBON_CHECK(import_ir.decl_id.has_value(),
                  "If we get invalid locations here, we may need to more "
                  "thoroughly track ImportDecls.");
 
@@ -72,7 +72,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
 
     // TODO: Add an "In implicit import of prelude." note for the case where we
     // don't have a location.
-    if (import_loc_id.is_valid()) {
+    if (import_loc_id.has_value()) {
       // TODO: Include the name of the imported library in the diagnostic.
       CARBON_DIAGNOSTIC(InImport, LocationInfo, "in import");
       context_fn(in_import_loc.loc, InImport);
@@ -103,21 +103,21 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
     if (auto diag_loc = handle_loc(loc.loc_id)) {
       return *diag_loc;
     }
-    CARBON_CHECK(cursor_inst_id.is_valid(), "Should have been set");
+    CARBON_CHECK(cursor_inst_id.has_value(), "Should have been set");
   }
 
   while (true) {
-    if (cursor_inst_id.is_valid()) {
+    if (cursor_inst_id.has_value()) {
       auto cursor_inst = cursor_ir->insts().Get(cursor_inst_id);
       if (auto bind_ref = cursor_inst.TryAs<SemIR::ExportDecl>();
-          bind_ref && bind_ref->value_id.is_valid()) {
+          bind_ref && bind_ref->value_id.has_value()) {
         cursor_inst_id = bind_ref->value_id;
         continue;
       }
 
       // If the parse node is valid, use it for the location.
       if (auto loc_id = cursor_ir->insts().GetLocId(cursor_inst_id);
-          loc_id.is_valid()) {
+          loc_id.has_value()) {
         if (auto diag_loc = handle_loc(loc_id)) {
           return *diag_loc;
         }
@@ -127,7 +127,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
       // If a namespace has an instruction for an import, switch to looking at
       // it.
       if (auto ns = cursor_inst.TryAs<SemIR::Namespace>()) {
-        if (ns->import_id.is_valid()) {
+        if (ns->import_id.has_value()) {
           cursor_inst_id = ns->import_id;
           continue;
         }
@@ -135,7 +135,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
     }
 
     // Invalid parse node but not an import; just nothing to point at.
-    return ConvertLocInFile(cursor_ir, Parse::NodeId::Invalid, loc.token_only,
+    return ConvertLocInFile(cursor_ir, Parse::NodeId::None, loc.token_only,
                             context_fn);
   }
 }
@@ -145,8 +145,8 @@ auto SemIRDiagnosticConverter::ConvertArg(llvm::Any arg) const -> llvm::Any {
     std::string library_name;
     if (*library_name_id == SemIR::LibraryNameId::Default) {
       library_name = "default library";
-    } else if (!library_name_id->is_valid()) {
-      library_name = "library <invalid>";
+    } else if (!library_name_id->has_value()) {
+      library_name = "library <none>";
     } else {
       RawStringOstream stream;
       stream << "library \""
@@ -161,7 +161,7 @@ auto SemIRDiagnosticConverter::ConvertArg(llvm::Any arg) const -> llvm::Any {
     return sem_ir_->names().GetFormatted(*name_id).str();
   }
   if (auto* type_of_expr = llvm::any_cast<TypeOfInstId>(&arg)) {
-    if (!type_of_expr->inst_id.is_valid()) {
+    if (!type_of_expr->inst_id.has_value()) {
       return "<none>";
     }
     // TODO: Where possible, produce a better description of the type based on

+ 1 - 1
toolchain/check/sem_ir_diagnostic_converter.h

@@ -58,7 +58,7 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLoc> {
   const SemIR::File* sem_ir_;
 
   // The last token encountered during processing.
-  Lex::TokenIndex last_token_ = Lex::TokenIndex::Invalid;
+  Lex::TokenIndex last_token_ = Lex::TokenIndex::None;
 };
 
 }  // namespace Carbon::Check

+ 9 - 9
toolchain/check/subst.cpp

@@ -41,7 +41,7 @@ class Worklist {
   auto back() -> WorklistItem& { return worklist_.back(); }
 
   auto Push(SemIR::InstId inst_id) -> void {
-    CARBON_CHECK(inst_id.is_valid());
+    CARBON_CHECK(inst_id.has_value());
     worklist_.push_back({.inst_id = inst_id,
                          .is_expanded = false,
                          .next_index = static_cast<int>(worklist_.size() + 1)});
@@ -69,19 +69,19 @@ static auto PushOperand(Context& context, Worklist& worklist,
   };
 
   auto push_specific = [&](SemIR::SpecificId specific_id) {
-    if (specific_id.is_valid()) {
+    if (specific_id.has_value()) {
       push_block(context.specifics().Get(specific_id).args_id);
     }
   };
 
   switch (kind) {
     case SemIR::IdKind::For<SemIR::InstId>:
-      if (SemIR::InstId inst_id(arg); inst_id.is_valid()) {
+      if (SemIR::InstId inst_id(arg); inst_id.has_value()) {
         worklist.Push(inst_id);
       }
       break;
     case SemIR::IdKind::For<SemIR::TypeId>:
-      if (SemIR::TypeId type_id(arg); type_id.is_valid()) {
+      if (SemIR::TypeId type_id(arg); type_id.has_value()) {
         worklist.Push(context.types().GetInstId(type_id));
       }
       break;
@@ -151,7 +151,7 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
   };
 
   auto pop_specific = [&](SemIR::SpecificId specific_id) {
-    if (!specific_id.is_valid()) {
+    if (!specific_id.has_value()) {
       return specific_id;
     }
     auto& specific = context.specifics().Get(specific_id);
@@ -162,14 +162,14 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind,
   switch (kind) {
     case SemIR::IdKind::For<SemIR::InstId>: {
       SemIR::InstId inst_id(arg);
-      if (!inst_id.is_valid()) {
+      if (!inst_id.has_value()) {
         return arg;
       }
       return worklist.Pop().index;
     }
     case SemIR::IdKind::For<SemIR::TypeId>: {
       SemIR::TypeId type_id(arg);
-      if (!type_id.is_valid()) {
+      if (!type_id.has_value()) {
         return arg;
       }
       return context.GetTypeIdForTypeInst(worklist.Pop()).index;
@@ -326,7 +326,7 @@ class SubstConstantCallbacks final : public SubstInstCallbacks {
       return true;
     }
 
-    auto entity_name_id = SemIR::EntityNameId::Invalid;
+    auto entity_name_id = SemIR::EntityNameId::None;
     if (auto bind =
             context_.insts().TryGetAs<SemIR::BindSymbolicName>(inst_id)) {
       entity_name_id = bind->entity_name_id;
@@ -358,7 +358,7 @@ class SubstConstantCallbacks final : public SubstInstCallbacks {
   // Rebuilds an instruction by building a new constant.
   auto Rebuild(SemIR::InstId /*old_inst_id*/, SemIR::Inst new_inst) const
       -> SemIR::InstId override {
-    auto result_id = TryEvalInst(context_, SemIR::InstId::Invalid, new_inst);
+    auto result_id = TryEvalInst(context_, SemIR::InstId::None, new_inst);
     CARBON_CHECK(result_id.is_constant(),
                  "Substitution into constant produced non-constant");
     return context_.constant_values().GetInstId(result_id);

+ 5 - 5
toolchain/check/testdata/alias/no_prelude/export_name.carbon

@@ -115,7 +115,7 @@ var d: D* = &c;
 // CHECK:STDOUT:     .C = imports.%Main.C
 // CHECK:STDOUT:     .D = %D
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   %D: type = export D, imports.%Main.D [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -146,7 +146,7 @@ var d: D* = &c;
 // CHECK:STDOUT:     .C = %C
 // CHECK:STDOUT:     .D = imports.%Main.D
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   %C: type = export C, imports.%Main.C [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -177,7 +177,7 @@ var d: D* = &c;
 // CHECK:STDOUT:     .D = imports.%Main.D
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %d.patt: %C = binding_pattern d
 // CHECK:STDOUT:     %.loc6: %C = var_pattern %d.patt
@@ -218,7 +218,7 @@ var d: D* = &c;
 // CHECK:STDOUT:     .D = imports.%Main.D
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %c.patt: <error> = binding_pattern c
 // CHECK:STDOUT:     %.loc10: <error> = var_pattern %c.patt
@@ -259,7 +259,7 @@ var d: D* = &c;
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %c.patt: %C = binding_pattern c
 // CHECK:STDOUT:     %.loc7: %C = var_pattern %c.patt

+ 1 - 1
toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon

@@ -55,7 +55,7 @@ fn F() -> {} {
 // CHECK:STDOUT: fn @F() -> %empty_struct_type {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc22_17: %empty_struct_type = struct_literal ()
-// CHECK:STDOUT:   %.loc22_12: <error> = bind_alias <invalid>, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc22_12: <error> = bind_alias <none>, <error> [template = <error>]
 // CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, file.%NS [template = file.%NS]
 // CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>

+ 1 - 1
toolchain/check/testdata/alias/no_prelude/fail_name_conflict.carbon

@@ -63,7 +63,7 @@ alias b = C;
 // CHECK:STDOUT:   %C.ref.loc23: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %b: ref %C = bind_name b, %b.var
 // CHECK:STDOUT:   %C.ref.loc31: type = name_ref C, %C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc31: type = bind_alias <invalid>, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %.loc31: type = bind_alias <none>, %C.decl [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {

+ 1 - 1
toolchain/check/testdata/alias/no_prelude/fail_params.carbon

@@ -31,7 +31,7 @@ alias A(T:! type) = T*;
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %T.ref: type = name_ref T, %T [symbolic = constants.%T]
 // CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic = constants.%ptr]
-// CHECK:STDOUT:   %T.param: type = value_param runtime_param<invalid>
+// CHECK:STDOUT:   %T.param: type = value_param runtime_param<none>
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0, %T.param [symbolic = constants.%T]
 // CHECK:STDOUT:   %A: <error> = bind_alias A, <error> [template = <error>]
 // CHECK:STDOUT: }

+ 4 - 4
toolchain/check/testdata/alias/no_prelude/import.carbon

@@ -130,7 +130,7 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .c_alias_alias = %c_alias_alias
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   %c_alias.ref.loc6: type = name_ref c_alias, imports.%Main.c_alias [template = constants.%C]
 // CHECK:STDOUT:   %c_alias_alias: type = bind_alias c_alias_alias, imports.%Main.c_alias [template = constants.%C]
 // CHECK:STDOUT:   name_binding_decl {
@@ -174,7 +174,7 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .b = imports.%Main.b
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %c.patt: %ptr = binding_pattern c
 // CHECK:STDOUT:     %.loc6_1: %ptr = var_pattern %c.patt
@@ -248,7 +248,7 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .a_alias_alias = %a_alias_alias
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   %a_alias.ref: ref %empty_tuple.type = name_ref a_alias, imports.%Main.a_alias
 // CHECK:STDOUT:   %a_alias_alias: ref %empty_tuple.type = bind_alias a_alias_alias, imports.%Main.a_alias
 // CHECK:STDOUT:   name_binding_decl {
@@ -290,7 +290,7 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .b = imports.%Main.b
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %c.patt: %empty_tuple.type = binding_pattern c
 // CHECK:STDOUT:     %.loc11_1: %empty_tuple.type = var_pattern %c.patt

+ 2 - 2
toolchain/check/testdata/alias/no_prelude/import_access.carbon

@@ -102,7 +102,7 @@ var inst: Test.A = {};
 // CHECK:STDOUT:     .inst = %inst
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Test.import = import Test
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %inst.patt: %C = binding_pattern inst
 // CHECK:STDOUT:     %.loc4: %C = var_pattern %inst.patt
@@ -143,7 +143,7 @@ var inst: Test.A = {};
 // CHECK:STDOUT:     .C = imports.%Test.C
 // CHECK:STDOUT:     .inst = %inst
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %inst.patt: <error> = binding_pattern inst
 // CHECK:STDOUT:     %.loc10: <error> = var_pattern %inst.patt

+ 2 - 2
toolchain/check/testdata/alias/no_prelude/import_order.carbon

@@ -64,7 +64,7 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc4_11: %C.elem = var_pattern %.loc4_16
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %C.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [template = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -108,7 +108,7 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:     .b_val = %b_val
 // CHECK:STDOUT:     .a_val = %a_val
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %d_val.patt: %C = binding_pattern d_val
 // CHECK:STDOUT:     %.loc7: %C = var_pattern %d_val.patt

+ 1 - 1
toolchain/check/testdata/alias/no_prelude/in_namespace.carbon

@@ -77,7 +77,7 @@ fn F() -> NS.a {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc11_11: %C.elem = var_pattern %.loc11_16
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %C.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [template = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/array/generic_empty.carbon

@@ -42,9 +42,9 @@ fn G(T:! type) {
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
 // CHECK:STDOUT:     %T.patt.loc11_6.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt)]
-// CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc11_6.1, runtime_param<invalid> [symbolic = %T.patt.loc11_6.2 (constants.%T.patt)]
+// CHECK:STDOUT:     %T.param_patt: type = value_param_pattern %T.patt.loc11_6.1, runtime_param<none> [symbolic = %T.patt.loc11_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.param: type = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %T.param: type = value_param runtime_param<none>
 // CHECK:STDOUT:     %T.loc11_6.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc11_6.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/array/import.carbon

@@ -91,7 +91,7 @@ fn G(n: i32) -> i32 {
 // CHECK:STDOUT:     .G = %G.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [template = constants.%G] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0

+ 2 - 2
toolchain/check/testdata/array/init_dependent_bound.carbon

@@ -76,9 +76,9 @@ fn H() { G(3); }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %N.patt.loc4_6.1: %i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc4_6.2 (constants.%N.patt.8e2)]
-// CHECK:STDOUT:     %N.param_patt: %i32 = value_param_pattern %N.patt.loc4_6.1, runtime_param<invalid> [symbolic = %N.patt.loc4_6.2 (constants.%N.patt.8e2)]
+// CHECK:STDOUT:     %N.param_patt: %i32 = value_param_pattern %N.patt.loc4_6.1, runtime_param<none> [symbolic = %N.patt.loc4_6.2 (constants.%N.patt.8e2)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %N.param: %i32 = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %N.param: %i32 = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc4: type = splice_block %i32.loc4 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc4: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc4: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]

+ 7 - 7
toolchain/check/testdata/as/adapter_conversion.carbon

@@ -254,12 +254,12 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <none>
 // CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [template = constants.%Make] {
 // CHECK:STDOUT:     %return.patt: %A = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %A = out_param_pattern %return.patt, runtime_param0
@@ -587,12 +587,12 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.y.871 [template = constants.%complete_type.70a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -701,12 +701,12 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.y.871 [template = constants.%complete_type.70a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -988,7 +988,7 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.ed6 [template = constants.%complete_type.1ec]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/as/overloaded.carbon

@@ -148,7 +148,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %X.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %X.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %X.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.n [template = constants.%complete_type.54b]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/basics/builtin_insts.carbon

@@ -14,10 +14,10 @@
 // CHECK:STDOUT: filename:        builtin_insts.carbon
 // CHECK:STDOUT: sem_ir:
 // CHECK:STDOUT:   import_irs:
-// CHECK:STDOUT:     ir0:             {decl_id: inst<invalid>, is_export: false}
+// CHECK:STDOUT:     ir0:             {decl_id: inst<none>, is_export: false}
 // CHECK:STDOUT:   import_ir_insts: {}
 // CHECK:STDOUT:   name_scopes:
-// CHECK:STDOUT:     name_scope0:     {inst: inst12, parent_scope: name_scope<invalid>, has_error: false, extended_scopes: [], names: {}}
+// CHECK:STDOUT:     name_scope0:     {inst: inst12, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
 // CHECK:STDOUT:   entity_names:    {}
 // CHECK:STDOUT:   functions:       {}
 // CHECK:STDOUT:   classes:         {}
@@ -44,7 +44,7 @@
 // CHECK:STDOUT:     'inst(StringType)': {kind: StringType, type: type(TypeType)}
 // CHECK:STDOUT:     'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
 // CHECK:STDOUT:     'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
-// CHECK:STDOUT:     inst12:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:     inst12:          {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     'inst(TypeType)':  template_constant(inst(TypeType))
 // CHECK:STDOUT:     'inst(AutoType)':  template_constant(inst(AutoType))

+ 1 - 1
toolchain/check/testdata/basics/no_prelude/verbose.carbon

@@ -12,7 +12,7 @@
 // NOAUTOUPDATE
 // SET-CHECK-SUBSET
 // CHECK:STDERR: Node Push 0: FunctionIntroducer -> <none>
-// CHECK:STDERR: AddPlaceholderInst: {kind: FunctionDecl, arg0: function<invalid>, arg1: inst_block_empty}
+// CHECK:STDERR: AddPlaceholderInst: {kind: FunctionDecl, arg0: function<none>, arg1: inst_block_empty}
 // CHECK:STDERR: ReplaceInst: inst{{[0-9]+}} -> {kind: FunctionDecl, arg0: function{{[0-9]+}}, arg1: inst_block_empty, type: type(inst{{[0-9]+}})}
 // CHECK:STDERR: inst_block_stack_ Push 1
 // CHECK:STDERR: AddInst: {kind: Return}

+ 4 - 4
toolchain/check/testdata/builtins/bool/eq.carbon

@@ -113,9 +113,9 @@ var d: C(false == false) = True();
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [template = constants.%C.generic] {
 // CHECK:STDOUT:     %B.patt.loc6_9.1: bool = symbolic_binding_pattern B, 0 [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
-// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc6_9.1, runtime_param<invalid> [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
+// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc6_9.1, runtime_param<none> [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.3 [template = bool] {
 // CHECK:STDOUT:       %bool.make_type: init type = call constants.%Bool() [template = bool]
 // CHECK:STDOUT:       %.loc6_13.2: type = value_of_initializer %bool.make_type [template = bool]
@@ -321,9 +321,9 @@ var d: C(false == false) = True();
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [template = constants.%C.generic] {
 // CHECK:STDOUT:     %B.patt.loc4_9.1: bool = symbolic_binding_pattern B, 0 [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
-// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc4_9.1, runtime_param<invalid> [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
+// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc4_9.1, runtime_param<none> [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.3 [template = bool] {
 // CHECK:STDOUT:       %bool.make_type: init type = call constants.%Bool() [template = bool]
 // CHECK:STDOUT:       %.loc4_13.2: type = value_of_initializer %bool.make_type [template = bool]

+ 1 - 1
toolchain/check/testdata/builtins/bool/make_type.carbon

@@ -76,7 +76,7 @@ var b: Bool() = false;
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %b.patt: bool = binding_pattern b
 // CHECK:STDOUT:     %.loc6_1: bool = var_pattern %b.patt

+ 4 - 4
toolchain/check/testdata/builtins/bool/neq.carbon

@@ -113,9 +113,9 @@ var d: C(false != false) = False();
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [template = constants.%C.generic] {
 // CHECK:STDOUT:     %B.patt.loc6_9.1: bool = symbolic_binding_pattern B, 0 [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
-// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc6_9.1, runtime_param<invalid> [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
+// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc6_9.1, runtime_param<none> [symbolic = %B.patt.loc6_9.2 (constants.%B.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.3 [template = bool] {
 // CHECK:STDOUT:       %bool.make_type: init type = call constants.%Bool() [template = bool]
 // CHECK:STDOUT:       %.loc6_13.2: type = value_of_initializer %bool.make_type [template = bool]
@@ -321,9 +321,9 @@ var d: C(false != false) = False();
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [template = constants.%C.generic] {
 // CHECK:STDOUT:     %B.patt.loc4_9.1: bool = symbolic_binding_pattern B, 0 [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
-// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc4_9.1, runtime_param<invalid> [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
+// CHECK:STDOUT:     %B.param_patt: bool = value_param_pattern %B.patt.loc4_9.1, runtime_param<none> [symbolic = %B.patt.loc4_9.2 (constants.%B.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %B.param: bool = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.3 [template = bool] {
 // CHECK:STDOUT:       %bool.make_type: init type = call constants.%Bool() [template = bool]
 // CHECK:STDOUT:       %.loc4_13.2: type = value_of_initializer %bool.make_type [template = bool]

+ 2 - 2
toolchain/check/testdata/builtins/float/make_type.carbon

@@ -125,7 +125,7 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:     .GetFloat = %GetFloat.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %f.patt: f64 = binding_pattern f
 // CHECK:STDOUT:     %.loc6_1: f64 = var_pattern %f.patt
@@ -220,7 +220,7 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:     .dyn = %dyn
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   %default.import = import <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %invalid_float.patt: <error> = binding_pattern invalid_float
 // CHECK:STDOUT:     %.loc10_1: <error> = var_pattern %invalid_float.patt

+ 3 - 3
toolchain/check/testdata/class/access_modifers.carbon

@@ -202,7 +202,7 @@ class A {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_11: %Circle.elem = var_pattern %.loc5_21
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Circle.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Circle.elem = var <none>
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %SOME_INTERNAL_CONSTANT.patt: %i32 = binding_pattern SOME_INTERNAL_CONSTANT
 // CHECK:STDOUT:   }
@@ -344,7 +344,7 @@ class A {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_13: %A.elem = var_pattern %.loc5_18
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x [template = constants.%complete_type.1ec]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -416,7 +416,7 @@ class A {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_11: %Circle.elem = var_pattern %.loc5_21
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Circle.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Circle.elem = var <none>
 // CHECK:STDOUT:   %GetRadius.decl: %GetRadius.type = fn_decl @GetRadius [template = constants.%GetRadius] {
 // CHECK:STDOUT:     %self.patt: %Circle = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %Circle = value_param_pattern %self.patt, runtime_param0

+ 2 - 2
toolchain/check/testdata/class/adapter/adapt.carbon

@@ -103,12 +103,12 @@ interface I {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %SomeClass.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %SomeClass.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %SomeClass.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/class/adapter/extend_adapt.carbon

@@ -213,12 +213,12 @@ fn F(a: IntAdapter) -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc7_3: %SomeClass.elem = var_pattern %.loc7_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc7: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc7: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %.loc8_8: %SomeClass.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc8_3: %SomeClass.elem = var_pattern %.loc8_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc8: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc8: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %StaticMemberFunction.decl: %StaticMemberFunction.type = fn_decl @StaticMemberFunction [template = constants.%StaticMemberFunction] {} {}
 // CHECK:STDOUT:   %AdapterMethod.decl: %AdapterMethod.type = fn_decl @AdapterMethod [template = constants.%AdapterMethod] {
 // CHECK:STDOUT:     %self.patt: %SomeClassAdapter = binding_pattern self
@@ -396,12 +396,12 @@ fn F(a: IntAdapter) -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %SomeClass.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %SomeClass.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %SomeClass.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 12 - 12
toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon

@@ -119,7 +119,7 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   adapt_decl %i32 [template]
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
-// CHECK:STDOUT:   %.loc15: %AdaptWithBase.elem = base_decl %Base.ref, element<invalid> [template]
+// CHECK:STDOUT:   %.loc15: %AdaptWithBase.elem = base_decl %Base.ref, element<none> [template]
 // CHECK:STDOUT:   complete_type_witness = <error>
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -162,11 +162,11 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   adapt_decl %i32 [template]
-// CHECK:STDOUT:   %.loc13_8: %AdaptWithField.elem = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   %.loc13_8: %AdaptWithField.elem = field_decl n, element<none> [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc13_3: %AdaptWithField.elem = var_pattern %.loc13_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %AdaptWithField.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %AdaptWithField.elem = var <none>
 // CHECK:STDOUT:   complete_type_witness = <error>
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -178,21 +178,21 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   adapt_decl %i32 [template]
-// CHECK:STDOUT:   %.loc25_8: %AdaptWithFields.elem = field_decl a, element<invalid> [template]
+// CHECK:STDOUT:   %.loc25_8: %AdaptWithFields.elem = field_decl a, element<none> [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc25_3: %AdaptWithFields.elem = var_pattern %.loc25_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc25: ref %AdaptWithFields.elem = var <invalid>
-// CHECK:STDOUT:   %.loc26_8: %AdaptWithFields.elem = field_decl b, element<invalid> [template]
+// CHECK:STDOUT:   %.var.loc25: ref %AdaptWithFields.elem = var <none>
+// CHECK:STDOUT:   %.loc26_8: %AdaptWithFields.elem = field_decl b, element<none> [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc26_3: %AdaptWithFields.elem = var_pattern %.loc26_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc26: ref %AdaptWithFields.elem = var <invalid>
-// CHECK:STDOUT:   %.loc27_8: %AdaptWithFields.elem = field_decl c, element<invalid> [template]
+// CHECK:STDOUT:   %.var.loc26: ref %AdaptWithFields.elem = var <none>
+// CHECK:STDOUT:   %.loc27_8: %AdaptWithFields.elem = field_decl c, element<none> [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc27_3: %AdaptWithFields.elem = var_pattern %.loc27_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc27: ref %AdaptWithFields.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc27: ref %AdaptWithFields.elem = var <none>
 // CHECK:STDOUT:   complete_type_witness = <error>
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -244,12 +244,12 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
-// CHECK:STDOUT:   %.loc7: %AdaptWithBaseAndFields.elem.767 = base_decl %Base.ref, element<invalid> [template]
-// CHECK:STDOUT:   %.loc8_8: %AdaptWithBaseAndFields.elem.ddf = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   %.loc7: %AdaptWithBaseAndFields.elem.767 = base_decl %Base.ref, element<none> [template]
+// CHECK:STDOUT:   %.loc8_8: %AdaptWithBaseAndFields.elem.ddf = field_decl n, element<none> [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc8_3: %AdaptWithBaseAndFields.elem.ddf = var_pattern %.loc8_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %AdaptWithBaseAndFields.elem.ddf = var <invalid>
+// CHECK:STDOUT:   %.var: ref %AdaptWithBaseAndFields.elem.ddf = var <none>
 // CHECK:STDOUT:   %.loc16_10: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc16_11: type = converted %.loc16_10, constants.%empty_struct_type [template = constants.%empty_struct_type]
 // CHECK:STDOUT:   adapt_decl %.loc16_11 [template]

+ 4 - 4
toolchain/check/testdata/class/adapter/init_adapt.carbon

@@ -217,12 +217,12 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %C.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %C.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %C.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.501 [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -403,12 +403,12 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %C.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <none>
 // CHECK:STDOUT:   %.loc6_8: %C.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc6_3: %C.elem = var_pattern %.loc6_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.501 [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/class/base.carbon

@@ -136,7 +136,7 @@ class Derived {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc4_3: %Base.elem = var_pattern %.loc4_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.b.0a3 [template = constants.%complete_type.ba8]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -152,7 +152,7 @@ class Derived {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.f8f [template = constants.%complete_type.da6]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -260,7 +260,7 @@ class Derived {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc7_3: %Derived.elem = var_pattern %.loc7_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Derived.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Derived.elem = var <none>
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.d [template = constants.%complete_type.860]
 // CHECK:STDOUT:   complete_type_witness = %complete_type

+ 5 - 5
toolchain/check/testdata/class/base_field.carbon

@@ -88,17 +88,17 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %.loc13_8: %Base.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc13_3: %Base.elem = var_pattern %.loc13_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %.loc14_8: %Base.elem = field_decl c, element2 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc14_3: %Base.elem = var_pattern %.loc14_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.c [template = constants.%complete_type.ebc]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -116,12 +116,12 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc20_3: %Derived.elem.344 = var_pattern %.loc20_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %.loc21_8: %Derived.elem.344 = field_decl e, element2 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc21_3: %Derived.elem.344 = var_pattern %.loc21_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.e.6a7 [template = constants.%complete_type.401]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/class/base_method.carbon

@@ -105,7 +105,7 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %self.patt: %ptr.11f = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %ptr.11f = value_param_pattern %self.patt, runtime_param0

+ 1 - 1
toolchain/check/testdata/class/basic.carbon

@@ -137,7 +137,7 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc18_3: %Class.elem = var_pattern %.loc18_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Class.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Class.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.k [template = constants.%complete_type.954]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/class/complete_in_member_fn.carbon

@@ -63,7 +63,7 @@ class C {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc14_3: %C.elem = var_pattern %.loc14_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %C.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 5 - 5
toolchain/check/testdata/class/compound_field.carbon

@@ -155,17 +155,17 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %.loc13_8: %Base.elem = field_decl b, element1 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc13_3: %Base.elem = var_pattern %.loc13_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %.loc14_8: %Base.elem = field_decl c, element2 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc14_3: %Base.elem = var_pattern %.loc14_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.c [template = constants.%complete_type.ebc]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -183,12 +183,12 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc20_3: %Derived.elem.344 = var_pattern %.loc20_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %.loc21_8: %Derived.elem.344 = field_decl e, element2 [template]
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc21_3: %Derived.elem.344 = var_pattern %.loc21_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.e.6a7 [template = constants.%complete_type.401]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/class/derived_to_base.carbon

@@ -206,7 +206,7 @@ fn ConvertInit() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %A.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.ba9 [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -222,7 +222,7 @@ fn ConvertInit() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc17_3: %B.elem.5c3 = var_pattern %.loc17_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %B.elem.5c3 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %B.elem.5c3 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.b.b44 [template = constants.%complete_type.725]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -240,7 +240,7 @@ fn ConvertInit() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc22_3: %C.elem.646 = var_pattern %.loc22_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %C.elem.646 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %C.elem.646 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.c.8e2 [template = constants.%complete_type.58a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 5 - 5
toolchain/check/testdata/class/fail_abstract.carbon

@@ -229,7 +229,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc15_3: <error> = var_pattern %.loc15_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
+// CHECK:STDOUT:   %.var: ref <error> = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -514,7 +514,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.c44 [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -599,7 +599,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -673,7 +673,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %Abstract.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Abstract.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Abstract.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -689,7 +689,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc11_3: %Derived.elem.344 = var_pattern %.loc11_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.c44 [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/class/fail_addr_not_self.carbon

@@ -56,9 +56,9 @@ class Class {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %a.patt.loc16_13.2: %ptr = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc16_13.1 (constants.%a.patt)]
-// CHECK:STDOUT:     %a.param_patt: %ptr = value_param_pattern %a.patt.loc16_13.2, runtime_param<invalid> [symbolic = %a.patt.loc16_13.1 (constants.%a.patt)]
+// CHECK:STDOUT:     %a.param_patt: %ptr = value_param_pattern %a.patt.loc16_13.2, runtime_param<none> [symbolic = %a.patt.loc16_13.1 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %a.param: %ptr = value_param runtime_param<invalid>
+// CHECK:STDOUT:     %a.param: %ptr = value_param runtime_param<none>
 // CHECK:STDOUT:     %.loc16: type = splice_block %ptr [template = constants.%ptr] {
 // CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
 // CHECK:STDOUT:       %ptr: type = ptr_type %Class [template = constants.%ptr]

+ 1 - 1
toolchain/check/testdata/class/fail_base_bad_type.carbon

@@ -833,7 +833,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc5_3: %Final.elem = var_pattern %.loc5_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %Final.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %Final.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/class/fail_compound_type_mismatch.carbon

@@ -84,7 +84,7 @@ fn AccessBInA(a: A) -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc12_3: %A.elem = var_pattern %.loc12_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %A.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
@@ -98,7 +98,7 @@ fn AccessBInA(a: A) -> i32 {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc16_3: %B.elem = var_pattern %.loc16_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref %B.elem = var <invalid>
+// CHECK:STDOUT:   %.var: ref %B.elem = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.b [template = constants.%complete_type.ba8]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/class/fail_convert_to_invalid.carbon

@@ -60,7 +60,7 @@ fn Make() -> C {
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %.loc16_3: <error> = var_pattern %.loc16_8
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
+// CHECK:STDOUT:   %.var: ref <error> = var <none>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff