generic.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. #ifndef CARBON_TOOLCHAIN_CHECK_GENERIC_H_
  5. #define CARBON_TOOLCHAIN_CHECK_GENERIC_H_
  6. #include "common/enum_mask_base.h"
  7. #include "toolchain/check/context.h"
  8. #include "toolchain/sem_ir/entity_with_params_base.h"
  9. #include "toolchain/sem_ir/ids.h"
  10. namespace Carbon::Check {
  11. // Start processing a declaration or definition that might be a generic entity.
  12. auto StartGenericDecl(Context& context) -> void;
  13. // Start processing a declaration or definition that might be a generic entity.
  14. auto StartGenericDefinition(Context& context, SemIR::GenericId generic_id)
  15. -> void;
  16. #define CARBON_DEPENDENT_INST_KIND(X) \
  17. /* The type of the instruction depends on a checked generic parameter. */ \
  18. X(SymbolicType) \
  19. /* The constant value of the instruction depends on a checked generic \
  20. * parameter. */ \
  21. X(SymbolicConstant) \
  22. X(Template)
  23. CARBON_DEFINE_RAW_ENUM_MASK(DependentInstKind, uint8_t) {
  24. CARBON_DEPENDENT_INST_KIND(CARBON_RAW_ENUM_MASK_ENUMERATOR)
  25. };
  26. // Represents a set of keyword modifiers, using a separate bit per modifier.
  27. class DependentInstKind : public CARBON_ENUM_MASK_BASE(DependentInstKind) {
  28. public:
  29. CARBON_DEPENDENT_INST_KIND(CARBON_ENUM_MASK_CONSTANT_DECL)
  30. };
  31. #define CARBON_DEPENDENT_INST_KIND_WITH_TYPE(X) \
  32. CARBON_ENUM_MASK_CONSTANT_DEFINITION(DependentInstKind, X)
  33. CARBON_DEPENDENT_INST_KIND(CARBON_DEPENDENT_INST_KIND_WITH_TYPE)
  34. #undef CARBON_DEPENDENT_INST_KIND_WITH_TYPE
  35. // An instruction that depends on a generic parameter in some way.
  36. struct DependentInst {
  37. SemIR::InstId inst_id;
  38. DependentInstKind kind;
  39. };
  40. // Attach a dependent instruction to the current generic, updating its type and
  41. // constant value as necessary.
  42. auto AttachDependentInstToCurrentGeneric(Context& context,
  43. DependentInst dependent_inst) -> void;
  44. // Discard the information about the current generic entity. This should be
  45. // called instead of `FinishGenericDecl` if the corresponding `Generic` object
  46. // would not actually be used, or when recovering from an error.
  47. auto DiscardGenericDecl(Context& context) -> void;
  48. // Finish processing a potentially generic declaration and produce a
  49. // corresponding generic object. Returns SemIR::GenericId::None if this
  50. // declaration is not actually generic.
  51. auto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId;
  52. // Builds eval block for the declaration.
  53. auto FinishGenericDecl(Context& context, SemIR::LocId loc_id,
  54. SemIR::GenericId generic_id) -> void;
  55. // BuildGeneric() and FinishGenericDecl() combined. Normally you would call this
  56. // function unless the caller has work to do between the two steps.
  57. auto BuildGenericDecl(Context& context, SemIR::InstId decl_id)
  58. -> SemIR::GenericId;
  59. // Merge a redeclaration of an entity that might be a generic into the original
  60. // declaration.
  61. auto FinishGenericRedecl(Context& context, SemIR::GenericId generic_id) -> void;
  62. // Finish processing a potentially generic definition.
  63. auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
  64. -> void;
  65. // Builds and returns an eval block, given the list of canonical symbolic
  66. // constants that the instructions in the eval block should produce. This is
  67. // used when importing a generic.
  68. auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
  69. SemIR::GenericInstIndex::Region region,
  70. llvm::ArrayRef<SemIR::InstId> const_ids)
  71. -> SemIR::InstBlockId;
  72. // Builds a new specific with a given argument list, or finds an existing one if
  73. // this generic has already been referenced with these arguments. Performs
  74. // substitution into the declaration, but not the definition, of the generic.
  75. auto MakeSpecific(Context& context, SemIR::LocId loc_id,
  76. SemIR::GenericId generic_id,
  77. llvm::ArrayRef<SemIR::InstId> args) -> SemIR::SpecificId;
  78. // Builds a new specific or finds an existing one in the case where the argument
  79. // list has already been converted into an instruction block. `args_id` should
  80. // be a canonical instruction block referring to constants.
  81. auto MakeSpecific(Context& context, SemIR::LocId loc_id,
  82. SemIR::GenericId generic_id, SemIR::InstBlockId args_id)
  83. -> SemIR::SpecificId;
  84. // Builds the specific that describes how the generic should refer to itself.
  85. // For example, for a generic `G(T:! type)`, this is the specific `G(T)`. If
  86. // `generic_id` is `None`, returns `None`.
  87. auto MakeSelfSpecific(Context& context, SemIR::LocId loc_id,
  88. SemIR::GenericId generic_id) -> SemIR::SpecificId;
  89. // Resolve the declaration of the given specific, by evaluating the eval block
  90. // of the corresponding generic and storing a corresponding value block in the
  91. // specific.
  92. auto ResolveSpecificDecl(Context& context, SemIR::LocId loc_id,
  93. SemIR::SpecificId specific_id) -> void;
  94. // Attempts to resolve the definition of the given specific, by evaluating the
  95. // eval block of the corresponding generic and storing a corresponding value
  96. // block in the specific. Returns false if a definition is not available.
  97. auto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,
  98. SemIR::SpecificId specific_id) -> bool;
  99. // Diagnoses if an entity has implicit parameters, indicating it's generic, but
  100. // is missing explicit parameters.
  101. auto DiagnoseIfGenericMissingExplicitParameters(
  102. Context& context, const SemIR::EntityWithParamsBase& entity_base) -> void;
  103. } // namespace Carbon::Check
  104. #endif // CARBON_TOOLCHAIN_CHECK_GENERIC_H_