Ver Fonte

Support deducing within the parameters of an interface type (#1278)

Richard Smith há 4 anos atrás
pai
commit
5c826df8bb

+ 18 - 1
explorer/interpreter/type_checker.cpp

@@ -553,11 +553,28 @@ auto TypeChecker::ArgumentDeduction(
       }
       return Success();
     }
+    case Value::Kind::InterfaceType: {
+      const auto& param_iface_type = cast<InterfaceType>(*param_type);
+      if (arg_type->kind() != Value::Kind::InterfaceType) {
+        return handle_non_deduced_type();
+      }
+      const auto& arg_iface_type = cast<InterfaceType>(*arg_type);
+      if (param_iface_type.declaration().name() !=
+          arg_iface_type.declaration().name()) {
+        return handle_non_deduced_type();
+      }
+      for (const auto& [ty, param_ty] : param_iface_type.args()) {
+        CARBON_RETURN_IF_ERROR(
+            ArgumentDeduction(source_loc, context, type_params, deduced,
+                              param_ty, arg_iface_type.args().at(ty),
+                              /*allow_implicit_conversion=*/false));
+      }
+      return Success();
+    }
     // For the following cases, we check the type matches.
     case Value::Kind::StaticArrayType:
       // FIXME: We could deduce the array type from an array or tuple argument.
     case Value::Kind::ContinuationType:
-    case Value::Kind::InterfaceType:
     case Value::Kind::ChoiceType:
     case Value::Kind::IntType:
     case Value::Kind::BoolType:

+ 27 - 0
explorer/testdata/impl/fail_param_interface_in_impl.carbon

@@ -0,0 +1,27 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// RUN: %{not} %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+
+package ExplorerTest api;
+
+interface Similar(T:! Type) {}
+
+impl forall [T:! Type] T as Similar(T) {}
+impl forall [T:! Type] i32 as Similar(T) {}
+
+fn CheckSimilar[T:! Type, U:! Similar(T)](a: T, b: U) {}
+
+fn Main() -> i32 {
+  let n: i32 = 0;
+  CheckSimilar(true, false);
+  CheckSimilar(true, n);
+  // CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/impl/fail_param_interface_in_impl.carbon:[[@LINE+1]]: could not find implementation of interface Similar(T = i32) for Bool
+  CheckSimilar(n, false);
+  return 0;
+}

+ 26 - 0
explorer/testdata/impl/param_interface_in_impl.carbon

@@ -0,0 +1,26 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// RUN: %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+// CHECK: result: 0
+
+package ExplorerTest api;
+
+interface Similar(T:! Type) {}
+
+impl forall [T:! Type] T as Similar(T) {}
+impl forall [T:! Type] i32 as Similar(T) {}
+
+fn CheckSimilar[T:! Type, U:! Similar(T)](a: T, b: U) {}
+
+fn Main() -> i32 {
+  let n: i32 = 0;
+  CheckSimilar(true, false);
+  CheckSimilar(true, n);
+  return 0;
+}