diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index acd09f5e5c75..84888484d43c 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -553,11 +553,28 @@ auto TypeChecker::ArgumentDeduction( } return Success(); } + case Value::Kind::InterfaceType: { + const auto& param_iface_type = cast(*param_type); + if (arg_type->kind() != Value::Kind::InterfaceType) { + return handle_non_deduced_type(); + } + const auto& arg_iface_type = cast(*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: diff --git a/explorer/testdata/impl/fail_param_interface_in_impl.carbon b/explorer/testdata/impl/fail_param_interface_in_impl.carbon new file mode 100644 index 000000000000..01e77cec361b --- /dev/null +++ b/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; +} diff --git a/explorer/testdata/impl/param_interface_in_impl.carbon b/explorer/testdata/impl/param_interface_in_impl.carbon new file mode 100644 index 000000000000..6a25f89a9350 --- /dev/null +++ b/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; +}