diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 2877990a3b6d8..2cfcb2669c002 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -629,8 +629,15 @@ class ASTContext final { ArrayRef params, Optional result, SILFunctionType::Representation trueRep); - /// Instantiates "Impl.Converter" if needed, then calls - /// ClangTypeConverter::getClangTemplateArguments. + /// Instantiates "Impl.Converter" if needed, then translate Swift generic + /// substitutions to equivalent C++ types using \p templateParams and \p + /// genericArgs. The converted Clang types are placed into \p templateArgs. + /// + /// \p templateArgs must be empty. \p templateParams and \p genericArgs must + /// be equal in size. + /// + /// \returns nullptr if successful. If an error occors, returns a list of + /// types that couldn't be converted. std::unique_ptr getClangTemplateArguments( const clang::TemplateParameterList *templateParams, ArrayRef genericArgs, diff --git a/include/swift/AST/ClangModuleLoader.h b/include/swift/AST/ClangModuleLoader.h index b02bac076b25a..4045e5c61792d 100644 --- a/include/swift/AST/ClangModuleLoader.h +++ b/include/swift/AST/ClangModuleLoader.h @@ -228,7 +228,7 @@ class ClangModuleLoader : public ModuleLoader { SubstitutionMap subst) = 0; }; -/// Used to describe a template instantiation error. +/// Describes a C++ template instantiation error. struct TemplateInstantiationError { /// Generic types that could not be converted to QualTypes using the /// ClangTypeConverter. diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index d44b2fa12a0a4..40090cbb5b451 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1692,7 +1692,7 @@ ERROR(where_nongeneric_toplevel,none, "declaration", ()) ERROR(unable_to_convert_generic_swift_types,none, "could not generate C++ types from the generic Swift types provided. " - "The following Swift type(s) provided to '%0' were unable to be " + "The following Swift type(s) provided to '%0' could not be " "converted: %1.", (StringRef, StringRef)) diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index 2abb77e5800fe..a42eee69cd919 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -860,12 +860,15 @@ ClangTypeConverter::getClangTemplateArguments( const clang::TemplateParameterList *templateParams, ArrayRef genericArgs, SmallVectorImpl &templateArgs) { + assert(templateArgs.size() == 0); + assert(genericArgs.size() == templateParams->size()); + // Keep track of the types we failed to convert so we can return a useful // error. SmallVector failedTypes; for (clang::NamedDecl *param : *templateParams) { // Note: all template parameters must be template type parameters. This is - // verified when we import the clang decl. + // verified when we import the Clang decl. auto templateParam = cast(param); auto replacement = genericArgs[templateParam->getIndex()]; auto qualType = convert(replacement); @@ -878,6 +881,9 @@ ClangTypeConverter::getClangTemplateArguments( } if (failedTypes.empty()) return nullptr; + // Clear "templateArgs" to prevent the clients from accidently reading a + // partially converted set of template arguments. + templateArgs.clear(); auto errorInfo = std::make_unique(); llvm::for_each(failedTypes, [&errorInfo](auto type) { errorInfo->failedTypes.push_back(type); diff --git a/lib/AST/ClangTypeConverter.h b/lib/AST/ClangTypeConverter.h index 55223b086e9dc..03bd54e33c174 100644 --- a/lib/AST/ClangTypeConverter.h +++ b/lib/AST/ClangTypeConverter.h @@ -84,10 +84,13 @@ class ClangTypeConverter : /// Swift declaration. Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl) const; - /// Translate Swift generic arguments to template arguments. + /// Translate Swift generic arguments to Clang C++ template arguments. /// - /// \returns nullptr if successful. If an error occors, returns a unique_ptr - /// to a `TemplateInstantiationError` with a list of the failed types. + /// \p templateArgs must be empty. \p templateParams and \p genericArgs must + /// be equal in size. + /// + /// \returns nullptr if successful. If an error occors, returns a list of + /// types that couldn't be converted. std::unique_ptr getClangTemplateArguments( const clang::TemplateParameterList *templateParams, ArrayRef genericArgs, diff --git a/test/Interop/Cxx/templates/Inputs/function-templates.h b/test/Interop/Cxx/templates/Inputs/function-templates.h index 45e6274c15755..e25771361e22f 100644 --- a/test/Interop/Cxx/templates/Inputs/function-templates.h +++ b/test/Interop/Cxx/templates/Inputs/function-templates.h @@ -1,28 +1,28 @@ #ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H #define TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATES_H -template T add(T a, T b) { return a + b; } +template T addSameTypeParams(T a, T b) { return a + b; } -template A addTwoTemplates(A a, B b) { return a + b; } +template A addMixedTypeParams(A a, B b) { return a + b; } template T passThrough(T value) { return value; } template const T passThroughConst(const T value) { return value; } void takesString(const char *) {} -template void expectsString(T str) { takesString(str); } +template void expectsConstCharPtr(T str) { takesString(str); } -template void integerTemplate() {} -template void defaultIntegerTemplate() {} +template void hasNonTypeTemplateParameter() {} +template void hasDefaultedNonTypeTemplateParameter() {} -// We cannot yet use this in swift but, make sure we don't crash when parsing +// We cannot yet use this in Swift but, make sure we don't crash when parsing // it. -template R returns_template(T a, U b) { +template R templateParameterReturnType(T a, U b) { return a + b; } // Same here: -template void cannot_infer_template() {} +template void cannotInferTemplate() {} struct HasVariadicMemeber { void test1(...) {} diff --git a/test/Interop/Cxx/templates/Inputs/member-templates.h b/test/Interop/Cxx/templates/Inputs/member-templates.h index acbea958a4606..f9ed0e0f3b0e0 100644 --- a/test/Interop/Cxx/templates/Inputs/member-templates.h +++ b/test/Interop/Cxx/templates/Inputs/member-templates.h @@ -1,7 +1,7 @@ struct HasMemberTemplates { - template T add(T a, T b) { return a + b; } + template T addSameTypeParams(T a, T b) { return a + b; } - template T addTwoTemplates(T a, U b) { return a + b; } + template T addMixedTypeParams(T a, U b) { return a + b; } template int addAll(int a, T b, U c) { return a + b + c; } diff --git a/test/Interop/Cxx/templates/function-template-errors.swift b/test/Interop/Cxx/templates/function-template-errors.swift deleted file mode 100644 index 28d163218d19e..0000000000000 --- a/test/Interop/Cxx/templates/function-template-errors.swift +++ /dev/null @@ -1,39 +0,0 @@ -// RUN: not %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop 2>&1 | %FileCheck %s - -// README: If you just added support for protocol composition to the -// ClangTypeConverter, please update this test to use a different type that we -// don't support so the error messages here are still tested. - - -import FunctionTemplates - -// Use protocol composition to create a type that we cannot (yet) turn into a clang::QualType. -protocol A { } -protocol B { } -protocol C { } - -// CHECK: error: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'passThrough' were unable to be converted: A & B. -public func caller1(x: A & B) -> A & B { - return passThrough(x) -} - -// CHECK: error: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'addTwoTemplates' were unable to be converted: A & B, A & C. -public func caller2(x: A & B, y: A & C) -> A & B { - return addTwoTemplates(x, y) -} - -// Make sure we emit an error and don't crash when failing to instantiate a function. -// CHECK: error: no matching function for call to 'takesString' -// CHECK: note: in instantiation of function template specialization 'expectsString' requested here -// CHECK: note: candidate function not viable: no known conversion from 'int' to 'const char *' for 1st argument -public func callExpectsString() { - expectsString(0 as Int32) -} - -// Make sure we don't import non-type template parameters. -// CHECK: error: cannot find 'integerTemplate' in scope -// CHECK: error: cannot find 'defaultIntegerTemplate' in scope -public func callIntegerTemplates() { - integerTemplate() - defaultIntegerTemplate() -} diff --git a/test/Interop/Cxx/templates/function-template-irgen.swift b/test/Interop/Cxx/templates/function-template-irgen.swift index b3ce1ef6b0801..fa5bd1c221605 100644 --- a/test/Interop/Cxx/templates/function-template-irgen.swift +++ b/test/Interop/Cxx/templates/function-template-irgen.swift @@ -20,20 +20,20 @@ public func testPassThrough(x: Int32) -> Int32 { return passThrough(x) } -// CHECK-LABEL: define {{.*}}i32 @"$s4main19testAddTwoTemplates1xs5Int32VAE_tF"(i32 %0) -// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %0, i32 %0) +// CHECK-LABEL: define {{.*}}i32 @"$s4main22testAddMixedTypeParams1xs5Int32VAE_tF"(i32 %0) +// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %0, i32 %0) // CHECK: ret i32 [[OUT_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z15addTwoTemplatesIiiET_S0_T0_|"\?\?\$addTwoTemplates@HH@@YAHHH@Z"}}(i32 %a, i32 %b) -public func testAddTwoTemplates(x: Int32) -> Int32 { - return addTwoTemplates(x, x) +// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z18addMixedTypeParamsIiiET_S0_T0_|"\?\?\$addMixedTypeParams@HH@@YAHHH@Z"}}(i32 %a, i32 %b) +public func testAddMixedTypeParams(x: Int32) -> Int32 { + return addMixedTypeParams(x, x) } -// CHECK-LABEL: define {{.*}}i32 @"$s4main7testAdd1xs5Int32VAE_tF"(i32 %0) -// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %0, i32 %0) +// CHECK-LABEL: define {{.*}}i32 @"$s4main21testAddSameTypeParams1xs5Int32VAE_tF"(i32 %0) +// CHECK: [[OUT_VAL:%.*]] = call i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %0, i32 %0) // CHECK: ret i32 [[OUT_VAL]] -// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z3addIiET_S0_S0_|"\?\?\$add@H@@YAHHH@Z"}}(i32 %a, i32 %b) -public func testAdd(x: Int32) -> Int32 { - return add(x, x) +// CHECK-LABEL: define linkonce_odr {{.*}}i32 @{{_Z17addSameTypeParamsIiET_S0_S0_|"\?\?\$addSameTypeParams@H@@YAHHH@Z"}}(i32 %a, i32 %b) +public func testAddSameTypeParams(x: Int32) -> Int32 { + return addSameTypeParams(x, x) } diff --git a/test/Interop/Cxx/templates/function-template-module-interface.swift b/test/Interop/Cxx/templates/function-template-module-interface.swift index 351d92bc2a5c3..1bd5411206e30 100644 --- a/test/Interop/Cxx/templates/function-template-module-interface.swift +++ b/test/Interop/Cxx/templates/function-template-module-interface.swift @@ -1,11 +1,11 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=FunctionTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s -// CHECK: func add(_ a: T, _ b: T) -> T -// CHECK: func addTwoTemplates(_ a: A, _ b: B) -> A +// CHECK: func addSameTypeParams(_ a: T, _ b: T) -> T +// CHECK: func addMixedTypeParams(_ a: A, _ b: B) -> A // CHECK: func passThrough(_ value: T) -> T // CHECK: func passThroughConst(_ value: T) -> T -// CHECK: func returns_template(_ a: T, _ b: U) -> R -// CHECK: func cannot_infer_template() +// CHECK: func templateParameterReturnType(_ a: T, _ b: U) -> R +// CHECK: func cannotInferTemplate() // CHECK: struct HasVariadicMemeber { // CHECK: @available(*, unavailable, message: "Variadic function is unavailable") diff --git a/test/Interop/Cxx/templates/function-template-silgen.swift b/test/Interop/Cxx/templates/function-template-silgen.swift index bfc5256fe2baf..fef7588225467 100644 --- a/test/Interop/Cxx/templates/function-template-silgen.swift +++ b/test/Interop/Cxx/templates/function-template-silgen.swift @@ -13,12 +13,12 @@ import FunctionTemplates // CHECK: [[PASS_THROUGH_FN:%.*]] = function_ref @{{_Z11passThroughIiET_S0_|\?\?\$passThrough@H@@YAHH@Z}} : $@convention(c) (Int32) -> Int32 // CHECK: [[B:%.*]] = apply [[PASS_THROUGH_FN]](%0) : $@convention(c) (Int32) -> Int32 -// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z15addTwoTemplatesIiiET_S0_T0_|\?\?\$addTwoTemplates@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32 +// CHECK: [[ADD_TWO_FN:%.*]] = function_ref @{{_Z18addMixedTypeParamsIiiET_S0_T0_|\?\?\$addMixedTypeParams@HH@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32 // CHECK: [[C:%.*]] = apply [[ADD_TWO_FN]]([[A]], [[B]]) : $@convention(c) (Int32, Int32) -> Int32 // CHECK: [[C_32_ADDR:%.*]] = alloc_stack $Int32 // CHECK: [[C_32:%.*]] = load [[C_32_ADDR]] : $*Int32 -// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z3addIiET_S0_S0_|\?\?\$add@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32 +// CHECK: [[ADD_FN:%.*]] = function_ref @{{_Z17addSameTypeParamsIiET_S0_S0_|\?\?\$addSameTypeParams@H@@YAHHH@Z}} : $@convention(c) (Int32, Int32) -> Int32 // CHECK: [[OUT:%.*]] = apply [[ADD_FN]]([[B]], [[C_32]]) : $@convention(c) (Int32, Int32) -> Int32 // CHECK: return [[OUT]] : $Int32 @@ -26,6 +26,6 @@ import FunctionTemplates public func test(x: Int32) -> Int32 { let a = passThroughConst(Int32(0)) let b = passThrough(x) - let c = addTwoTemplates(a, b) - return add(b, Int32(c)) + let c = addMixedTypeParams(a, b) + return addSameTypeParams(b, Int32(c)) } diff --git a/test/Interop/Cxx/templates/function-template-typechecker-errors.swift b/test/Interop/Cxx/templates/function-template-typechecker-errors.swift new file mode 100644 index 0000000000000..22db8d67572e6 --- /dev/null +++ b/test/Interop/Cxx/templates/function-template-typechecker-errors.swift @@ -0,0 +1,39 @@ +// RUN: not %target-typecheck-verify-swift %s -I %S/Inputs -enable-cxx-interop 2>&1 | %FileCheck %s + +// README: If you just added support for protocol composition to the +// ClangTypeConverter, please update this test to use a different type that we +// don't support so the error messages here are still tested. + + +import FunctionTemplates + +// Make sure we don't import non-type template parameters. +// CHECK: error: unexpected error produced: cannot find 'hasNonTypeTemplateParameter' in scope +// CHECK: error: unexpected error produced: cannot find 'hasDefaultedNonTypeTemplateParameter' in scope +public func callIntegerTemplates() { + hasNonTypeTemplateParameter() + hasDefaultedNonTypeTemplateParameter() +} + +// Use protocol composition to create a type that we cannot (yet) turn into a clang::QualType. +public protocol A { } +public protocol B { } +public protocol C { } + +// CHECK: error: unexpected error produced: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'passThrough' could not be converted: A & B. +public func caller1(x: A & B) -> A & B { + return passThrough(x) +} + +// CHECK: error: unexpected error produced: could not generate C++ types from the generic Swift types provided. The following Swift type(s) provided to 'addMixedTypeParams' could not be converted: A & B, A & C. +public func caller2(x: A & B, y: A & C) -> A & B { + return addMixedTypeParams(x, y) +} + +// Make sure we emit an error and don't crash when failing to instantiate a function. +// CHECK: error: diagnostic produced elsewhere: no matching function for call to 'takesString' +// CHECK: note: diagnostic produced elsewhere: in instantiation of function template specialization 'expectsConstCharPtr' requested here +// CHECK: note: diagnostic produced elsewhere: candidate function not viable: no known conversion from 'int' to 'const char *' for 1st argument +public func callexpectsConstCharPtr() { + expectsConstCharPtr(0 as Int32) +} diff --git a/test/Interop/Cxx/templates/function-template.swift b/test/Interop/Cxx/templates/function-template.swift index 1f42fe43fb486..d34e7004e27af 100644 --- a/test/Interop/Cxx/templates/function-template.swift +++ b/test/Interop/Cxx/templates/function-template.swift @@ -12,13 +12,13 @@ FunctionTemplateTestSuite.test("passThrough where T == Int") { expectEqual(42, result) } -FunctionTemplateTestSuite.test("add where T == Int") { - let result = add(42, 23) +FunctionTemplateTestSuite.test("addSameTypeParams where T == Int") { + let result = addSameTypeParams(42, 23) expectEqual(65, result) } -FunctionTemplateTestSuite.test("add where T, U == Int") { - let result = addTwoTemplates(42, 23) +FunctionTemplateTestSuite.test("addSameTypeParams where T, U == Int") { + let result = addMixedTypeParams(42, 23) expectEqual(65, result) } diff --git a/test/Interop/Cxx/templates/member-templates-module-interface.swift b/test/Interop/Cxx/templates/member-templates-module-interface.swift index 0045dfa3c196b..1a0690ae67ad2 100644 --- a/test/Interop/Cxx/templates/member-templates-module-interface.swift +++ b/test/Interop/Cxx/templates/member-templates-module-interface.swift @@ -1,8 +1,8 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=MemberTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s // CHECK: struct HasMemberTemplates { -// CHECK: mutating func add(_ a: T, _ b: T) -> T -// CHECK: mutating func addTwoTemplates(_ a: T, _ b: U) -> T +// CHECK: mutating func addSameTypeParams(_ a: T, _ b: T) -> T +// CHECK: mutating func addMixedTypeParams(_ a: T, _ b: U) -> T // CHECK: mutating func addAll(_ a: Int32, _ b: T, _ c: U) -> Int32 // CHECK: mutating func passThrough(_ val: T) -> T // CHECK: mutating func passThroughConst(_ val: T) -> T diff --git a/test/Interop/Cxx/templates/member-templates-silgen.swift b/test/Interop/Cxx/templates/member-templates-silgen.swift index 06d79cd851931..4c9ea02770780 100644 --- a/test/Interop/Cxx/templates/member-templates-silgen.swift +++ b/test/Interop/Cxx/templates/member-templates-silgen.swift @@ -8,10 +8,10 @@ import MemberTemplates // CHECK-LABEL: sil hidden @$s4main9basicTestyyF : $@convention(thin) () -> () -// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 +// CHECK: [[ADD:%.*]] = function_ref @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // CHECK: apply [[ADD]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 -// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26 +// CHECK: [[ADD_TWO_TEMPLATES:%.*]] = function_ref @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %26 // CHECK: apply [[ADD_TWO_TEMPLATES]]({{.*}}) : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // CHECK: [[ADD_ALL:%.*]] = function_ref @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32 // user: %39 @@ -24,15 +24,15 @@ import MemberTemplates func basicTest() { var i: Int32 = 0 var obj = HasMemberTemplates() - obj.add(i, i) - obj.addTwoTemplates(i, i) + obj.addSameTypeParams(i, i) + obj.addMixedTypeParams(i, i) obj.addAll(i, i, i) obj.doNothingConstRef(&i) } -// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addIiEET_S1_S1_] @_ZN18HasMemberTemplates3addIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 +// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_] @_ZN18HasMemberTemplates3addSameTypeParamsIiEET_S1_S1_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 -// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addTwoTemplatesIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 +// CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_] @_ZN18HasMemberTemplates15addMixedTypeParamsIiiEET_S1_T0_ : $@convention(c) (Int32, Int32, @inout HasMemberTemplates) -> Int32 // CHECK-LABEL: sil hidden_external [clang HasMemberTemplates._ZN18HasMemberTemplates6addAllIiiEEiiT_T0_] @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(c) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32 diff --git a/test/Interop/Cxx/templates/member-templates.swift b/test/Interop/Cxx/templates/member-templates.swift index 0a062f14535d4..741c2860868ef 100644 --- a/test/Interop/Cxx/templates/member-templates.swift +++ b/test/Interop/Cxx/templates/member-templates.swift @@ -19,8 +19,8 @@ TemplatesTestSuite.test("Set value - IntWrapper") { TemplatesTestSuite.test("Templated Add") { var h = HasMemberTemplates() - expectEqual(h.add(2, 1), 3) - expectEqual(h.addTwoTemplates(2, 1), 3) + expectEqual(h.addSameTypeParams(2, 1), 3) + expectEqual(h.addMixedTypeParams(2, 1), 3) } runAllTests()