diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 6182b43e83a50..655cd59b263fd 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -6273,7 +6273,7 @@ static ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext, auto out = new (rawMemory) TypeAliasDecl( typeDecl->getLoc(), typeDecl->getLoc(), typeDecl->getName(), typeDecl->getLoc(), nullptr, newContext); - out->setUnderlyingType(typeDecl->getInterfaceType()); + out->setUnderlyingType(typeDecl->getDeclaredInterfaceType()); out->setAccess(access); inheritance.setUnavailableIfNecessary(decl, out); return out; diff --git a/test/Interop/Cxx/class/inheritance/Inputs/module.modulemap b/test/Interop/Cxx/class/inheritance/Inputs/module.modulemap index c4702d40aa4fb..007e8f550b970 100644 --- a/test/Interop/Cxx/class/inheritance/Inputs/module.modulemap +++ b/test/Interop/Cxx/class/inheritance/Inputs/module.modulemap @@ -16,8 +16,8 @@ module ReferenceToDerived { requires cplusplus } -module SubTypes { - header "sub-types.h" +module NestedTypes { + header "nested-types.h" } module Subscripts { diff --git a/test/Interop/Cxx/class/inheritance/Inputs/sub-types.h b/test/Interop/Cxx/class/inheritance/Inputs/nested-types.h similarity index 83% rename from test/Interop/Cxx/class/inheritance/Inputs/sub-types.h rename to test/Interop/Cxx/class/inheritance/Inputs/nested-types.h index b5f013fe2eb32..866c21925a909 100644 --- a/test/Interop/Cxx/class/inheritance/Inputs/sub-types.h +++ b/test/Interop/Cxx/class/inheritance/Inputs/nested-types.h @@ -20,3 +20,5 @@ struct Base { }; struct Derived : Base {}; +struct Derived1 : Base {}; +struct Derived2 : Derived1 {}; diff --git a/test/Interop/Cxx/class/inheritance/sub-types-module-interface.swift b/test/Interop/Cxx/class/inheritance/nested-types-module-interface.swift similarity index 55% rename from test/Interop/Cxx/class/inheritance/sub-types-module-interface.swift rename to test/Interop/Cxx/class/inheritance/nested-types-module-interface.swift index 4029fc7ccb08c..201556b074e3e 100644 --- a/test/Interop/Cxx/class/inheritance/sub-types-module-interface.swift +++ b/test/Interop/Cxx/class/inheritance/nested-types-module-interface.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-ide-test -print-module -module-to-print=SubTypes -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s +// RUN: %target-swift-ide-test -print-module -module-to-print=NestedTypes -I %S/Inputs -source-filename=x -cxx-interoperability-mode=default | %FileCheck %s // CHECK: struct Base { // CHECK-NEXT: init() @@ -39,11 +39,29 @@ // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: struct Derived { +// CHECK: struct Derived { // CHECK-NEXT: init() -// CHECK-NEXT: typealias EnumClass = Base.EnumClass.Type -// CHECK-NEXT: typealias Enum = Base.Enum.Type -// CHECK-NEXT: typealias Struct = Base.Struct.Type -// CHECK-NEXT: typealias Parent = Base.Parent.Type -// CHECK-NEXT: typealias Union = Base.Union.Type +// CHECK-NEXT: typealias EnumClass = Base.EnumClass +// CHECK-NEXT: typealias Enum = Base.Enum +// CHECK-NEXT: typealias Struct = Base.Struct +// CHECK-NEXT: typealias Parent = Base.Parent +// CHECK-NEXT: typealias Union = Base.Union +// CHECK-NEXT: } + +// CHECK: struct Derived1 { +// CHECK-NEXT: init() +// CHECK-NEXT: typealias EnumClass = Base.EnumClass +// CHECK-NEXT: typealias Enum = Base.Enum +// CHECK-NEXT: typealias Struct = Base.Struct +// CHECK-NEXT: typealias Parent = Base.Parent +// CHECK-NEXT: typealias Union = Base.Union +// CHECK-NEXT: } + +// CHECK: struct Derived2 { +// CHECK-NEXT: init() +// CHECK-NEXT: typealias EnumClass = Base.EnumClass +// CHECK-NEXT: typealias Enum = Base.Enum +// CHECK-NEXT: typealias Struct = Base.Struct +// CHECK-NEXT: typealias Parent = Base.Parent +// CHECK-NEXT: typealias Union = Base.Union // CHECK-NEXT: } diff --git a/test/Interop/Cxx/class/inheritance/nested-types-typechecker.swift b/test/Interop/Cxx/class/inheritance/nested-types-typechecker.swift new file mode 100644 index 0000000000000..f56f8672d275c --- /dev/null +++ b/test/Interop/Cxx/class/inheritance/nested-types-typechecker.swift @@ -0,0 +1,113 @@ +// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default + +// This test ensures that nested type inherited from the base type are +// interchangeable with the base types themselves. + +import NestedTypes + +func parent( + bc: Base.EnumClass, + be: Base.Enum, + bs: Base.Struct, + bp: Base.Parent, + bpc: Base.Parent.Child, + bu: Base.Union, +) { + let dc: Derived.EnumClass = bc + let de: Derived.Enum = be + let ds: Derived.Struct = bs + let dp: Derived.Parent = bp + let dpc: Derived.Parent.Child = bpc + let du: Derived.Union = bu + + let _: Base.EnumClass = dc + let _: Base.Enum = de + let _: Base.Struct = ds + let _: Base.Parent = dp + let _: Base.Parent.Child = dpc + let _: Base.Union = du +} + +func grandparent( + bc: Base.EnumClass, + be: Base.Enum, + bs: Base.Struct, + bp: Base.Parent, + bpc: Base.Parent.Child, + bu: Base.Union, +) { + let dc: Derived2.EnumClass = bc + let de: Derived2.Enum = be + let ds: Derived2.Struct = bs + let dp: Derived2.Parent = bp + let dpc: Derived2.Parent.Child = bpc + let du: Derived2.Union = bu + + let _: Derived.EnumClass = dc + let _: Derived.Enum = de + let _: Derived.Struct = ds + let _: Derived.Parent = dp + let _: Derived.Parent.Child = dpc + let _: Derived.Union = du +} + +func siblings( + dc: Derived.EnumClass, + de: Derived.Enum, + ds: Derived.Struct, + dp: Derived.Parent, + dpc: Derived.Parent.Child, + du: Derived.Union, +) { + let _: Derived1.EnumClass = dc + let _: Derived1.Enum = de + let _: Derived1.Struct = ds + let _: Derived1.Parent = dp + let _: Derived1.Parent.Child = dpc + let _: Derived1.Union = du +} + +// Instances created from derived class can be type-annotated with base class +// and vice versa +func assigner() { + let _: Base.EnumClass = Derived.EnumClass.ecb + let _: Base.Enum = Derived.ea // expected-error {{type 'Derived' has no member 'ea'}} + // ^FIXME: nested enums are broken, so inherited nested enums are broken too + let _: Base.Struct = Derived.Struct(sa: 4, sb: 2) + let _: Base.Parent = Derived.Parent() + let _: Base.Parent.Child = Derived.Parent.Child(pca: 42) + let _: Base.Union = Derived.Union(ua: 42) + + let _: Derived.EnumClass = Base.EnumClass.ecc + let _: Derived.Enum = Base.ea // expected-error {{type 'Base' has no member 'ea'}} + // ^FIXME: nested enums are broken, so inherited nested enums are broken too + let _: Derived.Struct = Base.Struct(sa: 4, sb: 2) + let _: Derived.Parent = Base.Parent() + let _: Derived.Parent.Child = Base.Parent.Child(pca: 42) + let _: Derived.Union = Base.Union(ua: 42) +} + +// Extensions on base type should be "seen" in derived types too, and vice versa +extension Base.Parent { + static func getChild1() -> Child { + return Child(pca: 111) + } +} + +extension Derived { + func haveChild1() { + let _: Parent.Child = Parent.getChild1() + } +} + +extension Derived.Parent { + static func getChild2() -> Child { + return Child(pca: 111) + } +} + +extension Base { + func haveChild2() { + let _: Parent.Child = Parent.getChild2() + } +} diff --git a/test/Interop/Cxx/class/inheritance/type-aliases-module-interface.swift b/test/Interop/Cxx/class/inheritance/type-aliases-module-interface.swift index 4dde31f117869..66a28d63424ef 100644 --- a/test/Interop/Cxx/class/inheritance/type-aliases-module-interface.swift +++ b/test/Interop/Cxx/class/inheritance/type-aliases-module-interface.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-ide-test -print-module -module-to-print=TypeAliases -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s +// RUN: %target-swift-ide-test -print-module -module-to-print=TypeAliases -I %S/Inputs -source-filename=x -cxx-interoperability-mode=default | %FileCheck %s // CHECK: struct Base { // CHECK-NEXT: init() @@ -11,7 +11,7 @@ // CHECK-NEXT: struct Derived { // CHECK-NEXT: init() -// CHECK-NEXT: typealias Struct = Base.Struct.Type +// CHECK-NEXT: typealias Struct = Base.Struct // CHECK-NEXT: typealias T = Int32 // CHECK-NEXT: typealias U = Base.Struct // CHECK-NEXT: } diff --git a/test/Interop/Cxx/class/inheritance/type-aliases-typechecker.swift b/test/Interop/Cxx/class/inheritance/type-aliases-typechecker.swift new file mode 100644 index 0000000000000..a59bc3e3cfedb --- /dev/null +++ b/test/Interop/Cxx/class/inheritance/type-aliases-typechecker.swift @@ -0,0 +1,51 @@ +// RUN: %target-typecheck-verify-swift -I %S/Inputs -cxx-interoperability-mode=default + +// This test ensures that nested type aliases inherited from the base type are +// interchangeable with the base types themselves. + +import TypeAliases + +extension Derived { + func takesBaseTypes(bs: Base.Struct, bt: Base.T, bu: Base.U) { + let _: Struct = bs + let _: U = bs + + let _: T = bt + let _: Int32 = bt + + let _: U = bu + let _: Struct = bu + } + + func takesDerivedTypes(ds: Struct, dt: T, du: U) { + let _: Base.Struct = ds + let _: Base.U = ds + + let _: Base.T = dt + let _: Int32 = dt + + let _: Base.U = du + let _: Base.Struct = du + } +} +func takesBaseTypes(bs: Base.Struct, bt: Base.T, bu: Base.U) { + let _: Derived.Struct = bs + let _: Derived.U = bs + + let _: Derived.T = bt + let _: Int32 = bt + + let _: Derived.U = bu + let _: Derived.Struct = bu +} + +func takesDerivedTypes(ds: Derived.Struct, dt: Derived.T, du: Derived.U) { + let _: Base.Struct = ds + let _: Base.U = ds + + let _: Base.T = dt + let _: Int32 = dt + + let _: Base.U = du + let _: Base.Struct = du +}