facet_type.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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_FACET_TYPE_H_
  5. #define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_
  6. #include <compare>
  7. #include "toolchain/check/context.h"
  8. #include "toolchain/check/subst.h"
  9. #include "toolchain/sem_ir/entity_with_params_base.h"
  10. #include "toolchain/sem_ir/ids.h"
  11. namespace Carbon::Check {
  12. // Create a FacetType typed instruction object consisting of a interface. The
  13. // `specific_id` specifies arguments in the case the interface is generic.
  14. auto FacetTypeFromInterface(Context& context, SemIR::InterfaceId interface_id,
  15. SemIR::SpecificId specific_id) -> SemIR::FacetType;
  16. // Create a FacetType typed instruction object consisting of a named constraint.
  17. // The `specific_id` specifies arguments in the case the named constraint is
  18. // generic.
  19. auto FacetTypeFromNamedConstraint(Context& context,
  20. SemIR::NamedConstraintId named_constraint_id,
  21. SemIR::SpecificId specific_id)
  22. -> SemIR::FacetType;
  23. // Given an ImplWitnessAccessSubstituted, returns the InstId of the
  24. // ImplWitnessAccess. Otherwise, returns the input `inst_id` unchanged.
  25. //
  26. // This must be used when accessing the LHS of a rewrite constraint which has
  27. // not yet been resolved in order to preserve which associated constant is being
  28. // rewritten.
  29. auto GetImplWitnessAccessWithoutSubstitution(Context& context,
  30. SemIR::InstId inst_id)
  31. -> SemIR::InstId;
  32. // Perform rewrite constraint resolution for a facet type. The rewrite
  33. // constraints resolution is described here:
  34. // https://docs.carbon-lang.dev/docs/design/generics/appendix-rewrite-constraints.html#rewrite-constraint-resolution
  35. //
  36. // This function:
  37. // * Replaces the RHS of rewrite rules referring to `.Self` with the value
  38. // coming from other rewrite rules. For example in `.X = () and .Y = .X` the
  39. // result is `.X = () and .Y = ()`.
  40. // * Discards duplicate assignments to the same associated constant, such as in
  41. // `.X = () and .X = ()` which becomes just `.X = ()`.
  42. // * Diagnoses multiple assignments of different values to the same associated
  43. // constant such as `.X = () and .X = .Y`.
  44. // * Diagnoses cycles between rewrite rules such as `.X = .Y and .Y = .X` or
  45. // even `.X = .X`.
  46. //
  47. // The rewrite constraints in `rewrites` are modified in place and may be
  48. // reordered, with `ErrorInst` inserted when diagnosing errors.
  49. //
  50. // Returns false if resolve failed due to diagnosing an error. The resulting
  51. // value of the facet type should be an error constant.
  52. auto ResolveFacetTypeRewriteConstraints(
  53. Context& context, SemIR::LocId loc_id,
  54. llvm::SmallVector<SemIR::FacetTypeInfo::RewriteConstraint>& rewrites)
  55. -> bool;
  56. // Introduce `.Self` as a symbolic binding into the current scope, and return
  57. // the `SymbolicBinding` instruction.
  58. //
  59. // The type of `.Self` must be a `FacetType`, so that it gets wrapped in
  60. // `FacetAccessType` when used in a type position, such as in `U:! I(.Self)`.
  61. // This allows substitution with other facet values without requiring an
  62. // additional `FacetAccessType` to be inserted.
  63. auto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)
  64. -> SemIR::InstId;
  65. // Get a FacetType instruction for an empty FacetType. This is the facet
  66. // equivalent to TypeType.
  67. //
  68. // TODO: We vaguely plan to replace TypeType with this FacetType in the future,
  69. // though that's a big change.
  70. auto GetEmptyFacetType(Context& context) -> SemIR::TypeId;
  71. // Make a facet value for a type value, which has an empty FacetType as its
  72. // type. Returns a constant value, whose instruction payload is a FacetValue.
  73. auto GetConstantFacetValueForType(Context& context,
  74. SemIR::TypeInstId type_inst_id)
  75. -> SemIR::ConstantId;
  76. auto GetConstantFacetValueForTypeAndInterface(
  77. Context& context, SemIR::TypeInstId type_inst_id,
  78. SemIR::SpecificInterface specific_interface, SemIR::InstId witness_id)
  79. -> SemIR::ConstantId;
  80. class SubstPeriodSelfCallbacks : public SubstInstCallbacks {
  81. public:
  82. explicit SubstPeriodSelfCallbacks(
  83. Context* context, SemIR::LocId loc_id,
  84. SemIR::ConstantId period_self_replacement_id);
  85. auto Subst(SemIR::InstId& inst_id) -> SubstResult override;
  86. auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)
  87. -> SemIR::InstId override;
  88. virtual auto ShouldReplace(bool /*implicit*/) -> bool { return true; }
  89. auto loc_id() const -> SemIR::LocId { return loc_id_; }
  90. auto period_self_replacement_id() const -> SemIR::ConstantId {
  91. return period_self_replacement_id_;
  92. }
  93. private:
  94. auto GetReplacement(SemIR::InstId period_self, bool implicit)
  95. -> SemIR::InstId;
  96. auto ConvertReplacement(SemIR::InstId replacement_self_inst_id,
  97. SemIR::TypeId replacement_type_id,
  98. SemIR::TypeId period_self_type_id) -> SemIR::InstId;
  99. SemIR::LocId loc_id_;
  100. SemIR::ConstantId period_self_replacement_id_;
  101. // The last output of GetReplacement().
  102. SemIR::InstId cached_replacement_id_ = SemIR::InstId::None;
  103. // The type of the last output of GetReplacement(). If the type of `.Self`
  104. // matches, we can reuse the `cached_replacement_id_`.
  105. SemIR::TypeId cached_replacement_type_id_ = SemIR::TypeId::None;
  106. };
  107. // Replace all `.Self` references in `const_id`. The `callbacks` specifies the
  108. // facet to replace them with.
  109. auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
  110. SemIR::ConstantId const_id) -> SemIR::ConstantId;
  111. // Replace all `.Self` references in the specific of the interface or named
  112. // constraint. The `callbacks` specifies the facet to replace them with.
  113. auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
  114. SemIR::SpecificInterface interface)
  115. -> SemIR::SpecificInterface;
  116. auto SubstPeriodSelf(Context& context, SubstPeriodSelfCallbacks& callbacks,
  117. SemIR::SpecificNamedConstraint constraint)
  118. -> SemIR::SpecificNamedConstraint;
  119. } // namespace Carbon::Check
  120. #endif // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_