generic.h 5.3 KB

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