Skip to content

Commit 6ebb627

Browse files
authored
Merge pull request #5424 from slavapestov/fix-generic-method-overrides
2 parents 2dc96a9 + 2876437 commit 6ebb627

File tree

12 files changed

+148
-112
lines changed

12 files changed

+148
-112
lines changed

include/swift/AST/Types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
866866
Type getTypeOfMember(ModuleDecl *module, Type memberType,
867867
const DeclContext *memberDC);
868868

869+
/// Get the type of a superclass member as seen from the subclass,
870+
/// substituting generic parameters, dynamic Self return, and the
871+
/// 'self' argument type as appropriate.
872+
Type adjustSuperclassMemberDeclType(const ValueDecl *decl,
873+
const ValueDecl *parentDecl,
874+
Type memberType,
875+
LazyResolver *resolver);
876+
869877
/// Return T if this type is Optional<T>; otherwise, return the null type.
870878
Type getOptionalObjectType();
871879

lib/AST/Type.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3053,14 +3053,56 @@ Type TypeBase::getTypeOfMember(Module *module, Type memberType,
30533053
return memberType;
30543054

30553055
// Compute the set of member substitutions to apply.
3056-
TypeSubstitutionMap substitutions = getMemberSubstitutions(memberDC);
3056+
auto substitutions = getMemberSubstitutions(memberDC);
30573057
if (substitutions.empty())
30583058
return memberType;
30593059

30603060
// Perform the substitutions.
30613061
return memberType.subst(module, substitutions, None);
30623062
}
30633063

3064+
Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *decl,
3065+
const ValueDecl *parentDecl,
3066+
Type memberType,
3067+
LazyResolver *resolver) {
3068+
auto *DC = parentDecl->getDeclContext();
3069+
auto superclass = getSuperclassForDecl(
3070+
DC->getAsClassOrClassExtensionContext(), resolver);
3071+
auto subs = superclass->getMemberSubstitutions(DC);
3072+
3073+
if (auto *parentFunc = dyn_cast<AbstractFunctionDecl>(parentDecl)) {
3074+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
3075+
auto *genericParams = func->getGenericParams();
3076+
auto *parentParams = parentFunc->getGenericParams();
3077+
if (genericParams && parentParams &&
3078+
genericParams->size() == parentParams->size()) {
3079+
for (unsigned i = 0, e = genericParams->size(); i < e; i++) {
3080+
auto paramTy = parentParams->getParams()[i]->getDeclaredInterfaceType()
3081+
->getCanonicalType().getPointer();
3082+
subs[paramTy] = genericParams->getParams()[i]
3083+
->getDeclaredInterfaceType();
3084+
}
3085+
}
3086+
}
3087+
}
3088+
3089+
auto type = memberType.subst(parentDecl->getModuleContext(), subs);
3090+
3091+
if (isa<AbstractFunctionDecl>(parentDecl)) {
3092+
type = type->replaceSelfParameterType(this);
3093+
if (auto func = dyn_cast<FuncDecl>(parentDecl)) {
3094+
if (func->hasDynamicSelf()) {
3095+
type = type->replaceCovariantResultType(this,
3096+
func->getNumParameterLists());
3097+
}
3098+
} else if (isa<ConstructorDecl>(parentDecl)) {
3099+
type = type->replaceCovariantResultType(this, /*uncurryLevel=*/2);
3100+
}
3101+
}
3102+
3103+
return type;
3104+
}
3105+
30643106
Identifier DependentMemberType::getName() const {
30653107
if (NameOrAssocType.is<Identifier>())
30663108
return NameOrAssocType.get<Identifier>();

lib/SIL/SILFunctionType.cpp

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,10 +2041,14 @@ SILConstantInfo TypeConverter::getConstantOverrideInfo(SILDeclRef derived,
20412041
auto selfInterfaceTy = derivedInterfaceTy.getInput()->getRValueInstanceType();
20422042

20432043
auto overrideInterfaceTy =
2044-
selfInterfaceTy->getTypeOfMember(M.getSwiftModule(), baseInterfaceTy,
2045-
base.getDecl()->getDeclContext());
2046-
2047-
// Copy generic signature from derived to the override type
2044+
selfInterfaceTy->adjustSuperclassMemberDeclType(
2045+
derived.getDecl(), base.getDecl(), baseInterfaceTy,
2046+
/*resolver=*/nullptr);
2047+
2048+
// Copy generic signature from derived to the override type, to handle
2049+
// the case where the base member is not generic (because the base class
2050+
// is concrete) but the derived member is generic (because the derived
2051+
// class is generic).
20482052
if (auto derivedInterfaceFnTy = derivedInterfaceTy->getAs<GenericFunctionType>()) {
20492053
auto overrideInterfaceFnTy = overrideInterfaceTy->castTo<AnyFunctionType>();
20502054
overrideInterfaceTy =
@@ -2054,23 +2058,6 @@ SILConstantInfo TypeConverter::getConstantOverrideInfo(SILDeclRef derived,
20542058
overrideInterfaceFnTy->getExtInfo());
20552059
}
20562060

2057-
// Replace occurrences of 'Self' in the signature with the derived type.
2058-
// FIXME: these should all be modeled with a DynamicSelfType.
2059-
overrideInterfaceTy =
2060-
overrideInterfaceTy->replaceSelfParameterType(selfInterfaceTy);
2061-
2062-
bool hasDynamicSelf = false;
2063-
if (auto funcDecl = dyn_cast<FuncDecl>(derived.getDecl()))
2064-
hasDynamicSelf = funcDecl->hasDynamicSelf();
2065-
else if (isa<ConstructorDecl>(derived.getDecl()))
2066-
hasDynamicSelf = true;
2067-
2068-
if (hasDynamicSelf) {
2069-
overrideInterfaceTy =
2070-
overrideInterfaceTy->replaceCovariantResultType(selfInterfaceTy,
2071-
base.uncurryLevel + 1);
2072-
}
2073-
20742061
// Lower the formal AST type.
20752062
auto overrideLoweredInterfaceTy = getLoweredASTFunctionType(
20762063
cast<AnyFunctionType>(overrideInterfaceTy->getCanonicalType()),

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5014,32 +5014,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
50145014

50155015
void visitModuleDecl(ModuleDecl *) { }
50165016

5017-
/// Adjust the type of the given declaration to appear as if it were
5018-
/// in the given subclass of its actual declared class.
5019-
static Type adjustSuperclassMemberDeclType(TypeChecker &TC,
5020-
const ValueDecl *decl,
5021-
Type subclass) {
5022-
ClassDecl *superclassDecl =
5023-
decl->getDeclContext()->getDeclaredTypeInContext()
5024-
->getClassOrBoundGenericClass();
5025-
auto superclass = subclass;
5026-
while (superclass->getClassOrBoundGenericClass() != superclassDecl)
5027-
superclass = TC.getSuperClassOf(superclass);
5028-
auto type = TC.substMemberTypeWithBase(decl->getModuleContext(), decl,
5029-
superclass,
5030-
/*isTypeReference=*/false);
5031-
if (auto func = dyn_cast<FuncDecl>(decl)) {
5032-
if (func->hasDynamicSelf()) {
5033-
type = type->replaceCovariantResultType(subclass,
5034-
func->getNumParameterLists());
5035-
}
5036-
} else if (isa<ConstructorDecl>(decl)) {
5037-
type = type->replaceCovariantResultType(subclass, /*uncurryLevel=*/2);
5038-
}
5039-
5040-
return type;
5041-
}
5042-
50435017
/// Perform basic checking to determine whether a declaration can override a
50445018
/// declaration in a superclass.
50455019
static bool areOverrideCompatibleSimple(ValueDecl *decl,
@@ -5093,15 +5067,15 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
50935067

50945068
static bool
50955069
diagnoseMismatchedOptionals(TypeChecker &TC,
5096-
const Decl *member,
5070+
const ValueDecl *member,
50975071
const ParameterList *params,
50985072
TypeLoc resultTL,
50995073
const ValueDecl *parentMember,
51005074
Type owningTy,
51015075
bool treatIUOResultAsError) {
51025076
bool emittedError = false;
5103-
Type plainParentTy = adjustSuperclassMemberDeclType(TC, parentMember,
5104-
owningTy);
5077+
Type plainParentTy = owningTy->adjustSuperclassMemberDeclType(
5078+
member, parentMember, parentMember->getInterfaceType(), &TC);
51055079
const auto *parentTy = plainParentTy->castTo<AnyFunctionType>();
51065080
if (isa<AbstractFunctionDecl>(parentMember))
51075081
parentTy = parentTy->getResult()->castTo<AnyFunctionType>();
@@ -5538,8 +5512,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
55385512

55395513
// Check whether the types are identical.
55405514
// FIXME: It's wrong to use the uncurried types here for methods.
5541-
auto parentDeclTy = adjustSuperclassMemberDeclType(TC, parentDecl,
5542-
owningTy);
5515+
auto parentDeclTy = owningTy->adjustSuperclassMemberDeclType(
5516+
decl, parentDecl, parentDecl->getInterfaceType(), &TC);
55435517
parentDeclTy = parentDeclTy->getUnlabeledType(TC.Context);
55445518
if (method) {
55455519
parentDeclTy = parentDeclTy->castTo<AnyFunctionType>()->getResult();
@@ -5807,8 +5781,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
58075781
}
58085782
} else if (auto property = dyn_cast_or_null<VarDecl>(abstractStorage)) {
58095783
auto propertyTy = property->getInterfaceType();
5810-
auto parentPropertyTy = adjustSuperclassMemberDeclType(TC, matchDecl,
5811-
superclass);
5784+
auto parentPropertyTy = superclass->adjustSuperclassMemberDeclType(
5785+
decl, matchDecl, matchDecl->getInterfaceType(), &TC);
58125786

58135787
if (!propertyTy->canOverride(parentPropertyTy,
58145788
OverrideMatchMode::Strict,

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
206206
// concrete type, or resolve its components down to another dependent member.
207207
if (auto alias = nestedPA->getTypeAliasDecl()) {
208208
return TC.substMemberTypeWithBase(DC->getParentModule(), alias,
209-
baseTy, true);
209+
baseTy);
210210
}
211211

212212
Identifier name = ref->getIdentifier();

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
369369

370370
// Substitute the base into the member's type.
371371
auto memberType = substMemberTypeWithBase(dc->getParentModule(),
372-
typeDecl, type,
373-
/*isTypeReference=*/true);
372+
typeDecl, type);
374373

375374
// FIXME: It is not clear why this substitution can fail, but the
376375
// standard library won't build without this check.

lib/Sema/TypeCheckType.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ Type TypeChecker::resolveTypeInContext(
337337
}
338338

339339
return substMemberTypeWithBase(parentDC->getParentModule(), typeDecl,
340-
fromType, /*isTypeReference=*/true);
340+
fromType);
341341
}
342342
}
343343

@@ -378,7 +378,7 @@ Type TypeChecker::resolveTypeInContext(
378378
}
379379

380380
return substMemberTypeWithBase(parentDC->getParentModule(), typeDecl,
381-
fromType, /*isTypeReference=*/true);
381+
fromType);
382382
}
383383

384384
if (auto superclassTy = getSuperClassOf(fromType))
@@ -1142,8 +1142,7 @@ static Type resolveNestedIdentTypeComponent(
11421142

11431143
// Otherwise, simply substitute the parent type into the member.
11441144
memberType = TC.substMemberTypeWithBase(DC->getParentModule(), typeDecl,
1145-
parentTy,
1146-
/*isTypeReference=*/true);
1145+
parentTy);
11471146

11481147
// Propagate failure.
11491148
if (!memberType || memberType->hasError()) return memberType;
@@ -2797,21 +2796,18 @@ Type TypeResolver::buildProtocolType(
27972796
}
27982797

27992798
Type TypeChecker::substMemberTypeWithBase(Module *module,
2800-
const ValueDecl *member,
2801-
Type baseTy, bool isTypeReference) {
2802-
Type memberType = isTypeReference
2803-
? cast<TypeDecl>(member)->getDeclaredInterfaceType()
2804-
: member->getInterfaceType();
2805-
if (isTypeReference) {
2806-
// The declared interface type for a generic type will have the type
2807-
// arguments; strip them off.
2808-
if (auto nominalTypeDecl = dyn_cast<NominalTypeDecl>(member)) {
2809-
if (auto boundGenericTy = memberType->getAs<BoundGenericType>()) {
2810-
memberType = UnboundGenericType::get(
2811-
const_cast<NominalTypeDecl *>(nominalTypeDecl),
2812-
boundGenericTy->getParent(),
2813-
Context);
2814-
}
2799+
const TypeDecl *member,
2800+
Type baseTy) {
2801+
Type memberType = member->getDeclaredInterfaceType();
2802+
2803+
// The declared interface type for a generic type will have the type
2804+
// arguments; strip them off.
2805+
if (auto nominalTypeDecl = dyn_cast<NominalTypeDecl>(member)) {
2806+
if (auto boundGenericTy = memberType->getAs<BoundGenericType>()) {
2807+
memberType = UnboundGenericType::get(
2808+
const_cast<NominalTypeDecl *>(nominalTypeDecl),
2809+
boundGenericTy->getParent(),
2810+
Context);
28152811
}
28162812
}
28172813

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -855,17 +855,14 @@ class TypeChecker final : public LazyResolver {
855855
bool isGenericSignature,
856856
GenericTypeResolver *resolver);
857857

858-
/// \brief Substitute the given base type into the type of the given member,
859-
/// producing the effective type that the member will have.
858+
/// \brief Substitute the given base type into the type of the given nested type,
859+
/// producing the effective type that the nested type will have.
860860
///
861861
/// \param module The module in which the substitution will be performed.
862862
/// \param member The member whose type projection is being computed.
863863
/// \param baseTy The base type that will be substituted for the 'Self' of the
864864
/// member.
865-
/// \param isTypeReference Whether this is a reference to a type declaration
866-
/// within a type context.
867-
Type substMemberTypeWithBase(Module *module, const ValueDecl *member,
868-
Type baseTy, bool isTypeReference);
865+
Type substMemberTypeWithBase(Module *module, const TypeDecl *member, Type baseTy);
869866

870867
/// \brief Retrieve the superclass type of the given type, or a null type if
871868
/// the type has no supertype.

stdlib/public/core/ContiguousArrayBuffer.swift

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ internal var _emptyArrayStorage : _EmptyArrayStorage {
5959
Builtin.addressof(&_swiftEmptyArrayStorage))
6060
}
6161

62-
// FIXME(ABI)#141 : This whole class is a workaround for
63-
// <rdar://problem/18560464> Can't override generic method in generic
64-
// subclass. If it weren't for that bug, we'd override
65-
// _withVerbatimBridgedUnsafeBuffer directly in
66-
// _ContiguousArrayStorage<Element>.
67-
// rdar://problem/19341002
68-
class _ContiguousArrayStorage1 : _ContiguousArrayStorageBase {
62+
// The class that implements the storage for a ContiguousArray<Element>
63+
@_versioned
64+
final class _ContiguousArrayStorage<Element> : _ContiguousArrayStorageBase {
65+
66+
deinit {
67+
_elementPointer.deinitialize(count: countAndCapacity.count)
68+
_fixLifetime(self)
69+
}
70+
6971
#if _runtime(_ObjC)
7072
/// If the `Element` is bridged verbatim, invoke `body` on an
7173
/// `UnsafeBufferPointer` to the elements and return the result.
@@ -82,28 +84,7 @@ class _ContiguousArrayStorage1 : _ContiguousArrayStorageBase {
8284

8385
/// If `Element` is bridged verbatim, invoke `body` on an
8486
/// `UnsafeBufferPointer` to the elements.
85-
internal func _withVerbatimBridgedUnsafeBufferImpl(
86-
_ body: (UnsafeBufferPointer<AnyObject>) throws -> Void
87-
) rethrows {
88-
_sanityCheckFailure(
89-
"Must override _withVerbatimBridgedUnsafeBufferImpl in derived classes")
90-
}
91-
#endif
92-
}
93-
94-
// The class that implements the storage for a ContiguousArray<Element>
95-
@_versioned
96-
final class _ContiguousArrayStorage<Element> : _ContiguousArrayStorage1 {
97-
98-
deinit {
99-
_elementPointer.deinitialize(count: countAndCapacity.count)
100-
_fixLifetime(self)
101-
}
102-
103-
#if _runtime(_ObjC)
104-
/// If `Element` is bridged verbatim, invoke `body` on an
105-
/// `UnsafeBufferPointer` to the elements.
106-
internal final override func _withVerbatimBridgedUnsafeBufferImpl(
87+
internal final func _withVerbatimBridgedUnsafeBufferImpl(
10788
_ body: (UnsafeBufferPointer<AnyObject>) throws -> Void
10889
) rethrows {
10990
if _isBridgedVerbatimToObjectiveC(Element.self) {

stdlib/public/core/Unicode.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import SwiftShims
2222
/// of a decoding error.
2323
///
2424
/// - SeeAlso: `UnicodeCodec.decode(next:)`
25+
@_fixed_layout
2526
public enum UnicodeDecodingResult : Equatable {
2627
/// A decoded Unicode scalar value.
2728
case scalarValue(UnicodeScalar)

test/SILGen/vtable_thunks_reabstraction.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,33 @@ class ConcreteOptional<X>: Opaque<S?> {
9292
override func variantOptionality(x: S??) -> S? { return x! }
9393
}
9494
*/
95+
96+
// Make sure we remap the method's innermost generic parameters
97+
// to the correct depth
98+
class GenericBase<T> {
99+
func doStuff<U>(t: T, u: U) {}
100+
init<U>(t: T, u: U) {}
101+
}
102+
103+
class ConcreteSub : GenericBase<Int> {
104+
override func doStuff<U>(t: Int, u: U) {
105+
super.doStuff(t: t, u: u)
106+
}
107+
override init<U>(t: Int, u: U) {
108+
super.init(t: t, u: u)
109+
}
110+
}
111+
112+
class ConcreteBase {
113+
init<U>(t: Int, u: U) {}
114+
func doStuff<U>(t: Int, u: U) {}
115+
}
116+
117+
class GenericSub<T> : ConcreteBase {
118+
override init<U>(t: Int, u: U) {
119+
super.init(t: t, u: u)
120+
}
121+
override func doStuff<U>(t: Int, u: U) {
122+
super.doStuff(t: t, u: u)
123+
}
124+
}

0 commit comments

Comments
 (0)