impl_scope.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 "explorer/interpreter/impl_scope.h"
  5. #include "explorer/interpreter/type_checker.h"
  6. #include "explorer/interpreter/value.h"
  7. #include "llvm/ADT/StringExtras.h"
  8. #include "llvm/Support/Casting.h"
  9. using llvm::cast;
  10. using llvm::dyn_cast;
  11. namespace Carbon {
  12. void ImplScope::Add(Nonnull<const Value*> iface, Nonnull<const Value*> type,
  13. Nonnull<Expression*> impl,
  14. const TypeChecker& type_checker) {
  15. Add(iface, {}, type, {}, impl, type_checker);
  16. }
  17. void ImplScope::Add(Nonnull<const Value*> iface,
  18. llvm::ArrayRef<Nonnull<const GenericBinding*>> deduced,
  19. Nonnull<const Value*> type,
  20. llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
  21. Nonnull<Expression*> impl_expr,
  22. const TypeChecker& type_checker) {
  23. if (auto* constraint = dyn_cast<ConstraintType>(iface)) {
  24. BindingMap map;
  25. map[constraint->self_binding()] = type;
  26. for (size_t i = 0; i != constraint->impl_constraints().size(); ++i) {
  27. ConstraintType::ImplConstraint impl = constraint->impl_constraints()[i];
  28. Add(cast<InterfaceType>(type_checker.Substitute(map, impl.interface)),
  29. deduced, type_checker.Substitute(map, impl.type), impl_bindings,
  30. type_checker.MakeConstraintWitnessAccess(impl_expr, i), type_checker);
  31. }
  32. return;
  33. }
  34. impls_.push_back({.interface = cast<InterfaceType>(iface),
  35. .deduced = deduced,
  36. .type = type,
  37. .impl_bindings = impl_bindings,
  38. .impl = impl_expr});
  39. }
  40. void ImplScope::AddParent(Nonnull<const ImplScope*> parent) {
  41. parent_scopes_.push_back(parent);
  42. }
  43. auto ImplScope::Resolve(Nonnull<const Value*> constraint_type,
  44. Nonnull<const Value*> impl_type,
  45. SourceLocation source_loc,
  46. const TypeChecker& type_checker) const
  47. -> ErrorOr<Nonnull<Expression*>> {
  48. if (const auto* iface_type = dyn_cast<InterfaceType>(constraint_type)) {
  49. return ResolveInterface(iface_type, impl_type, source_loc, type_checker);
  50. }
  51. if (const auto* constraint = dyn_cast<ConstraintType>(constraint_type)) {
  52. std::vector<Nonnull<Expression*>> witnesses;
  53. BindingMap map;
  54. map[constraint->self_binding()] = impl_type;
  55. for (auto impl : constraint->impl_constraints()) {
  56. CARBON_ASSIGN_OR_RETURN(
  57. Nonnull<Expression*> result,
  58. ResolveInterface(
  59. cast<InterfaceType>(type_checker.Substitute(map, impl.interface)),
  60. type_checker.Substitute(map, impl.type), source_loc,
  61. type_checker));
  62. witnesses.push_back(result);
  63. }
  64. // TODO: Check satisfaction of same-type constraints.
  65. return type_checker.MakeConstraintWitness(*constraint, std::move(witnesses),
  66. source_loc);
  67. }
  68. CARBON_FATAL() << "expected a constraint, not " << *constraint_type;
  69. }
  70. auto ImplScope::ResolveInterface(Nonnull<const InterfaceType*> iface_type,
  71. Nonnull<const Value*> type,
  72. SourceLocation source_loc,
  73. const TypeChecker& type_checker) const
  74. -> ErrorOr<Nonnull<Expression*>> {
  75. CARBON_ASSIGN_OR_RETURN(
  76. std::optional<Nonnull<Expression*>> result,
  77. TryResolve(iface_type, type, source_loc, *this, type_checker));
  78. if (!result.has_value()) {
  79. return CompilationError(source_loc) << "could not find implementation of "
  80. << *iface_type << " for " << *type;
  81. }
  82. return *result;
  83. }
  84. auto ImplScope::TryResolve(Nonnull<const InterfaceType*> iface_type,
  85. Nonnull<const Value*> type,
  86. SourceLocation source_loc,
  87. const ImplScope& original_scope,
  88. const TypeChecker& type_checker) const
  89. -> ErrorOr<std::optional<Nonnull<Expression*>>> {
  90. CARBON_ASSIGN_OR_RETURN(
  91. std::optional<Nonnull<Expression*>> result,
  92. ResolveHere(iface_type, type, source_loc, original_scope, type_checker));
  93. for (Nonnull<const ImplScope*> parent : parent_scopes_) {
  94. CARBON_ASSIGN_OR_RETURN(std::optional<Nonnull<Expression*>> parent_result,
  95. parent->TryResolve(iface_type, type, source_loc,
  96. original_scope, type_checker));
  97. if (parent_result.has_value()) {
  98. if (result.has_value()) {
  99. return CompilationError(source_loc) << "ambiguous implementations of "
  100. << *iface_type << " for " << *type;
  101. } else {
  102. result = *parent_result;
  103. }
  104. }
  105. }
  106. return result;
  107. }
  108. auto ImplScope::ResolveHere(Nonnull<const InterfaceType*> iface_type,
  109. Nonnull<const Value*> impl_type,
  110. SourceLocation source_loc,
  111. const ImplScope& original_scope,
  112. const TypeChecker& type_checker) const
  113. -> ErrorOr<std::optional<Nonnull<Expression*>>> {
  114. std::optional<Nonnull<Expression*>> result = std::nullopt;
  115. for (const Impl& impl : impls_) {
  116. std::optional<Nonnull<Expression*>> m = type_checker.MatchImpl(
  117. *iface_type, impl_type, impl, original_scope, source_loc);
  118. if (m.has_value()) {
  119. if (result.has_value()) {
  120. return CompilationError(source_loc)
  121. << "ambiguous implementations of " << *iface_type << " for "
  122. << *impl_type;
  123. } else {
  124. result = *m;
  125. }
  126. }
  127. }
  128. return result;
  129. }
  130. // TODO: Add indentation when printing the parents.
  131. void ImplScope::Print(llvm::raw_ostream& out) const {
  132. out << "impls: ";
  133. llvm::ListSeparator sep;
  134. for (const Impl& impl : impls_) {
  135. out << sep << *(impl.type) << " as " << *(impl.interface);
  136. }
  137. out << "\n";
  138. for (const Nonnull<const ImplScope*>& parent : parent_scopes_) {
  139. out << *parent;
  140. }
  141. }
  142. } // namespace Carbon