Skip to content

[4.1] [ClangImporter] Handle subscript getters redeclared in subclasses #13505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6348,8 +6348,6 @@ SwiftDeclConverter::importSubscript(Decl *decl,
->getAsNominalTypeOrNominalTypeExtensionContext() ==
setter->getDeclContext()
->getAsNominalTypeOrNominalTypeExtensionContext());
// TODO: Possible that getter and setter are different instantiations
// of the same objc generic type?

// Whether we can update the types involved in the subscript
// operation.
Expand Down Expand Up @@ -6404,8 +6402,16 @@ SwiftDeclConverter::importSubscript(Decl *decl,
}
}

// The context into which the subscript should go.
bool associateWithSetter = setter && !getterAndSetterInSameType;
// The context into which the subscript should go. We prefer wherever the
// getter is declared unless the two accessors are in different types and the
// one we started with is the setter. This happens when:
// - A read-only subscript is made read/write is a subclass.
// - A setter is redeclared in a subclass, but not the getter.
// And not when:
// - A getter is redeclared in a subclass, but not the setter.
// - The getter and setter are part of the same type.
// - There is no setter.
bool associateWithSetter = !getterAndSetterInSameType && setter == decl;
DeclContext *dc =
associateWithSetter ? setter->getDeclContext() : getter->getDeclContext();

Expand Down
31 changes: 31 additions & 0 deletions test/ClangImporter/Inputs/custom-modules/ObjCSubscripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,34 @@
- (NSString *)objectForKeyedSubscript:(NSString *)subscript;
- (void)setObject:(NSString *)object forKeyedSubscript:(NSString *)key;
@end


// rdar://problem/36033356 failed specifically when the base class was never
// subscripted, so please don't mention this class in the .swift file.
@interface KeySubscriptBase
- (id)objectForKeyedSubscript:(NSString *)subscript;
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
@end

@interface KeySubscriptOverrideGetter : KeySubscriptBase
- (id)objectForKeyedSubscript:(NSString *)subscript;
@end

@interface KeySubscriptOverrideSetter : KeySubscriptBase
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
@end

// rdar://problem/36033356 failed specifically when the base class was never
// subscripted, so please don't mention this class in the .swift file.
@interface KeySubscriptReversedBase
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
- (id)objectForKeyedSubscript:(NSString *)subscript;
@end

@interface KeySubscriptReversedOverrideGetter : KeySubscriptReversedBase
- (id)objectForKeyedSubscript:(NSString *)subscript;
@end

@interface KeySubscriptReversedOverrideSetter : KeySubscriptReversedBase
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
@end
21 changes: 21 additions & 0 deletions test/ClangImporter/objc_subscript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,24 @@ class ConformsToKeySubscriptProto2 : KeySubscriptProto2 {
set { }
}
}

func testOverridesWithoutBase(
o1: KeySubscriptOverrideGetter,
o2: KeySubscriptOverrideSetter,
o3: KeySubscriptReversedOverrideGetter,
o4: KeySubscriptReversedOverrideSetter
) {
// rdar://problem/36033356 failed specifically when the base class was never
// subscripted, so please don't mention the base classes here.
_ = o1["abc"]
o1["abc"] = "xyz"

_ = o2["abc"]
o2["abc"] = "xyz"

_ = o3["abc"]
o3["abc"] = "xyz"

_ = o4["abc"]
o4["abc"] = "xyz"
}