type.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/check/type.h"
  5. #include "toolchain/check/eval.h"
  6. #include "toolchain/check/facet_type.h"
  7. #include "toolchain/check/type_completion.h"
  8. #include "toolchain/sem_ir/facet_type_info.h"
  9. namespace Carbon::Check {
  10. // Enforces that an integer type has a valid bit width.
  11. auto ValidateIntType(Context& context, SemIR::LocId loc_id,
  12. SemIR::IntType result) -> bool {
  13. auto bit_width =
  14. context.insts().TryGetAs<SemIR::IntValue>(result.bit_width_id);
  15. if (!bit_width) {
  16. // Symbolic bit width.
  17. return true;
  18. }
  19. const auto& bit_width_val = context.ints().Get(bit_width->int_id);
  20. if (bit_width_val.isZero() ||
  21. (context.types().IsSignedInt(bit_width->type_id) &&
  22. bit_width_val.isNegative())) {
  23. CARBON_DIAGNOSTIC(IntWidthNotPositive, Error,
  24. "integer type width of {0} is not positive", TypedInt);
  25. context.emitter().Emit(
  26. loc_id, IntWidthNotPositive,
  27. {.type = bit_width->type_id, .value = bit_width_val});
  28. return false;
  29. }
  30. if (bit_width_val.ugt(IntStore::MaxIntWidth)) {
  31. CARBON_DIAGNOSTIC(IntWidthTooLarge, Error,
  32. "integer type width of {0} is greater than the "
  33. "maximum supported width of {1}",
  34. TypedInt, int);
  35. context.emitter().Emit(loc_id, IntWidthTooLarge,
  36. {.type = bit_width->type_id, .value = bit_width_val},
  37. IntStore::MaxIntWidth);
  38. return false;
  39. }
  40. return true;
  41. }
  42. // Enforces that the bit width is 64 for a float.
  43. auto ValidateFloatBitWidth(Context& context, SemIR::LocId loc_id,
  44. SemIR::InstId inst_id) -> bool {
  45. auto inst = context.insts().GetAs<SemIR::IntValue>(inst_id);
  46. if (context.ints().Get(inst.int_id) == 64) {
  47. return true;
  48. }
  49. CARBON_DIAGNOSTIC(CompileTimeFloatBitWidth, Error, "bit width must be 64");
  50. context.emitter().Emit(loc_id, CompileTimeFloatBitWidth);
  51. return false;
  52. }
  53. // Enforces that a float type has a valid bit width.
  54. auto ValidateFloatType(Context& context, SemIR::LocId loc_id,
  55. SemIR::FloatType result) -> bool {
  56. auto bit_width =
  57. context.insts().TryGetAs<SemIR::IntValue>(result.bit_width_id);
  58. if (!bit_width) {
  59. // Symbolic bit width.
  60. return true;
  61. }
  62. return ValidateFloatBitWidth(context, loc_id, result.bit_width_id);
  63. }
  64. // Gets or forms a type_id for a type, given the instruction kind and arguments.
  65. template <typename InstT, typename... EachArgT>
  66. static auto GetTypeImpl(Context& context, EachArgT... each_arg)
  67. -> SemIR::TypeId {
  68. InstT inst = {SemIR::TypeType::TypeId, each_arg...};
  69. return context.types().GetTypeIdForTypeConstantId(TryEvalInst(context, inst));
  70. }
  71. // Gets or forms a type_id for a type, given the instruction kind and arguments,
  72. // and completes the type. This should only be used when type completion cannot
  73. // fail.
  74. template <typename InstT, typename... EachArgT>
  75. static auto GetCompleteTypeImpl(Context& context, EachArgT... each_arg)
  76. -> SemIR::TypeId {
  77. auto type_id = GetTypeImpl<InstT>(context, each_arg...);
  78. CompleteTypeOrCheckFail(context, type_id);
  79. return type_id;
  80. }
  81. auto GetStructType(Context& context, SemIR::StructTypeFieldsId fields_id)
  82. -> SemIR::TypeId {
  83. return GetTypeImpl<SemIR::StructType>(context, fields_id);
  84. }
  85. auto GetTupleType(Context& context, llvm::ArrayRef<SemIR::InstId> type_inst_ids)
  86. -> SemIR::TypeId {
  87. return GetTypeImpl<SemIR::TupleType>(
  88. context, context.inst_blocks().AddCanonical(type_inst_ids));
  89. }
  90. auto GetAssociatedEntityType(Context& context, SemIR::InterfaceId interface_id,
  91. SemIR::SpecificId interface_specific_id)
  92. -> SemIR::TypeId {
  93. return GetTypeImpl<SemIR::AssociatedEntityType>(context, interface_id,
  94. interface_specific_id);
  95. }
  96. auto GetConstType(Context& context, SemIR::TypeInstId inner_type_id)
  97. -> SemIR::TypeId {
  98. return GetTypeImpl<SemIR::ConstType>(context, inner_type_id);
  99. }
  100. auto GetSingletonType(Context& context, SemIR::TypeInstId singleton_id)
  101. -> SemIR::TypeId {
  102. CARBON_CHECK(SemIR::IsSingletonInstId(singleton_id));
  103. auto type_id = context.types().GetTypeIdForTypeInstId(singleton_id);
  104. // To keep client code simpler, complete builtin types before returning them.
  105. CompleteTypeOrCheckFail(context, type_id);
  106. return type_id;
  107. }
  108. auto GetClassType(Context& context, SemIR::ClassId class_id,
  109. SemIR::SpecificId specific_id) -> SemIR::TypeId {
  110. return GetTypeImpl<SemIR::ClassType>(context, class_id, specific_id);
  111. }
  112. auto GetFunctionType(Context& context, SemIR::FunctionId fn_id,
  113. SemIR::SpecificId specific_id) -> SemIR::TypeId {
  114. return GetCompleteTypeImpl<SemIR::FunctionType>(context, fn_id, specific_id);
  115. }
  116. auto GetFunctionTypeWithSelfType(Context& context,
  117. SemIR::TypeInstId interface_function_type_id,
  118. SemIR::InstId self_id) -> SemIR::TypeId {
  119. return GetCompleteTypeImpl<SemIR::FunctionTypeWithSelfType>(
  120. context, interface_function_type_id, self_id);
  121. }
  122. auto GetGenericClassType(Context& context, SemIR::ClassId class_id,
  123. SemIR::SpecificId enclosing_specific_id)
  124. -> SemIR::TypeId {
  125. return GetCompleteTypeImpl<SemIR::GenericClassType>(context, class_id,
  126. enclosing_specific_id);
  127. }
  128. auto GetGenericInterfaceType(Context& context, SemIR::InterfaceId interface_id,
  129. SemIR::SpecificId enclosing_specific_id)
  130. -> SemIR::TypeId {
  131. return GetCompleteTypeImpl<SemIR::GenericInterfaceType>(
  132. context, interface_id, enclosing_specific_id);
  133. }
  134. auto GetInterfaceType(Context& context, SemIR::InterfaceId interface_id,
  135. SemIR::SpecificId specific_id) -> SemIR::TypeId {
  136. return GetTypeImpl<SemIR::FacetType>(
  137. context,
  138. FacetTypeFromInterface(context, interface_id, specific_id).facet_type_id);
  139. }
  140. auto GetFacetType(Context& context, const SemIR::FacetTypeInfo& info)
  141. -> SemIR::TypeId {
  142. return GetTypeImpl<SemIR::FacetType>(context,
  143. context.facet_types().Add(info));
  144. }
  145. auto GetPointerType(Context& context, SemIR::TypeInstId pointee_type_id)
  146. -> SemIR::TypeId {
  147. return GetTypeImpl<SemIR::PointerType>(context, pointee_type_id);
  148. }
  149. auto GetPatternType(Context& context, SemIR::TypeId scrutinee_type_id)
  150. -> SemIR::TypeId {
  151. CARBON_CHECK(!context.types().Is<SemIR::PatternType>(scrutinee_type_id),
  152. "Type is already a pattern type");
  153. if (scrutinee_type_id == SemIR::ErrorInst::TypeId) {
  154. return SemIR::ErrorInst::TypeId;
  155. }
  156. return GetTypeImpl<SemIR::PatternType>(
  157. context, context.types().GetInstId(scrutinee_type_id));
  158. }
  159. auto GetUnboundElementType(Context& context, SemIR::TypeInstId class_type_id,
  160. SemIR::TypeInstId element_type_id) -> SemIR::TypeId {
  161. return GetTypeImpl<SemIR::UnboundElementType>(context, class_type_id,
  162. element_type_id);
  163. }
  164. auto GetCanonicalizedFacetOrTypeValue(Context& context, SemIR::InstId inst_id)
  165. -> SemIR::InstId {
  166. // We can have FacetAccessType of a FacetValue, and a FacetValue of a
  167. // FacetAccessType, but they don't nest indefinitely.
  168. if (auto access = context.insts().TryGetAs<SemIR::FacetAccessType>(inst_id)) {
  169. inst_id = access->facet_value_inst_id;
  170. }
  171. if (auto value = context.insts().TryGetAs<SemIR::FacetValue>(inst_id)) {
  172. inst_id = value->type_inst_id;
  173. if (auto access =
  174. context.insts().TryGetAs<SemIR::FacetAccessType>(inst_id)) {
  175. inst_id = access->facet_value_inst_id;
  176. }
  177. }
  178. CARBON_CHECK(!context.insts().Is<SemIR::FacetAccessType>(inst_id));
  179. CARBON_CHECK(!context.insts().Is<SemIR::FacetValue>(inst_id));
  180. return context.constant_values().GetConstantInstId(inst_id);
  181. }
  182. auto GetCanonicalizedFacetOrTypeValue(Context& context,
  183. SemIR::ConstantId const_id)
  184. -> SemIR::ConstantId {
  185. return context.constant_values().Get(GetCanonicalizedFacetOrTypeValue(
  186. context, context.constant_values().GetInstId(const_id)));
  187. }
  188. } // namespace Carbon::Check