impl_lookup.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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_IMPL_LOOKUP_H_
  5. #define CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_
  6. #include <variant>
  7. #include "toolchain/check/context.h"
  8. #include "toolchain/sem_ir/ids.h"
  9. #include "toolchain/sem_ir/inst.h"
  10. #include "toolchain/sem_ir/typed_insts.h"
  11. namespace Carbon::Check {
  12. // Looks up the witnesses to use for a type value or facet value, and a facet
  13. // type naming a set of interfaces required to be implemented for that type, as
  14. // well as possible constraints on those interfaces.
  15. //
  16. // N.B. In the future, `TypeType` will become a facet type, at which point type
  17. // values will also be facet values.
  18. //
  19. // The return value is one of:
  20. // - An InstBlockId value, containing an `ImplWitness` instruction for each
  21. // required interface in the `query_facet_type_const_id`. This verifies the
  22. // facet type is satisfied for the type in `type_const_id`, and provides a
  23. // witness for accessing the impl of each interface.
  24. //
  25. // - `InstBlockId::None`, indicating lookup failed for at least one required
  26. // interface in the `query_facet_type_const_id`. The facet type is not
  27. // satisfied for the type in `type_const_id`. This represents lookup failure,
  28. // but is not an error, so no diagnostic is emitted.
  29. //
  30. // - An error value, indicating the program is invalid and a diagonstic has been
  31. // produced, either in this function or before.
  32. auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
  33. SemIR::ConstantId query_self_const_id,
  34. SemIR::ConstantId query_facet_type_const_id)
  35. -> SemIR::InstBlockIdOrError;
  36. // The result of EvalLookupSingleImplWitness(). It can be one of:
  37. // - No value. Lookup failed to find an impl declaration.
  38. // - A concrete value. Lookup found a concrete impl declaration that can be
  39. // used definitively.
  40. // - A symbolic value. Lookup found an impl but it is not returned since lookup
  41. // will need to be done again with a more specific query to look for
  42. // specializations.
  43. class [[nodiscard]] EvalImplLookupResult {
  44. public:
  45. static auto MakeNone() -> EvalImplLookupResult {
  46. return EvalImplLookupResult(SemIR::InstId::None);
  47. }
  48. static auto MakeFinal(SemIR::InstId inst_id) -> EvalImplLookupResult {
  49. return EvalImplLookupResult(inst_id);
  50. }
  51. static auto MakeNonFinal() -> EvalImplLookupResult {
  52. return EvalImplLookupResult(FoundNonFinalImpl());
  53. }
  54. // True if a concrete impl witness was found or a non-final impl. In the
  55. // latter case the InstId of the impl's witness is not returned, only the fact
  56. // that it exists.
  57. auto has_value() const -> bool {
  58. return std::holds_alternative<FoundNonFinalImpl>(result_) ||
  59. std::get<SemIR::InstId>(result_).has_value();
  60. }
  61. // True if there is a concrete witness in the result. If false, and
  62. // `has_value()` is true, it means a non-final impl was found and a further
  63. // more specific query will need to be done.
  64. auto has_concrete_value() const -> bool {
  65. const auto* inst_id = std::get_if<SemIR::InstId>(&result_);
  66. return inst_id && inst_id->has_value();
  67. }
  68. // Only valid if `has_concrete_value()` is true. Returns the witness id for
  69. // the found impl declaration, or None if `has_value()` is false.
  70. auto concrete_witness() const -> SemIR::InstId {
  71. return std::get<SemIR::InstId>(result_);
  72. }
  73. private:
  74. struct FoundNonFinalImpl {};
  75. explicit EvalImplLookupResult(SemIR::InstId inst_id) : result_(inst_id) {}
  76. explicit EvalImplLookupResult(FoundNonFinalImpl f) : result_(f) {}
  77. std::variant<SemIR::InstId, FoundNonFinalImpl> result_;
  78. };
  79. // Looks for a witness instruction of an impl declaration for a query consisting
  80. // of a type value or facet value, and a single interface. This is for eval to
  81. // execute lookup via the LookupImplWitness instruction. It does not consider
  82. // the self facet value for finding a witness, since LookupImplWitness() would
  83. // have found that and not caused us to defer lookup to here.
  84. auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
  85. SemIR::LookupImplWitness eval_query,
  86. SemIR::InstId non_canonical_query_self_inst_id)
  87. -> EvalImplLookupResult;
  88. } // namespace Carbon::Check
  89. #endif // CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_