Skip to content

Commit 8256bd1

Browse files
committed
---
yaml --- r: 348156 b: refs/heads/master c: b05eb4a h: refs/heads/master
1 parent b9a008e commit 8256bd1

File tree

14 files changed

+377
-9
lines changed

14 files changed

+377
-9
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: fcf67c1044cf8b0a08d56063b24a8853f7b41bed
2+
refs/heads/master: b05eb4aa9326f47fc498b9da807a490cc8452a2c
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
396396
83)
397397

398398
SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly,
399-
OnImport | UserInaccessible,
399+
OnImport | OnFunc | OnConstructor | OnVar | OnSubscript | UserInaccessible,
400400
84)
401401
DECL_ATTR(_custom, Custom,
402402
OnAnyDecl | UserInaccessible,

trunk/include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,6 +2490,18 @@ WARNING(warn_implementation_only_conflict,none,
24902490
NOTE(implementation_only_conflict_here,none,
24912491
"imported as implementation-only here", ())
24922492

2493+
ERROR(implementation_only_decl_non_override,none,
2494+
"'@_implementationOnly' can only be used on overrides", ())
2495+
ERROR(implementation_only_override_changed_type,none,
2496+
"'@_implementationOnly' override must have the same type as the "
2497+
"declaration it overrides (%0)", (Type))
2498+
ERROR(implementation_only_override_without_attr,none,
2499+
"override of '@_implementationOnly' %0 should also be declared "
2500+
"'@_implementationOnly'", (DescriptiveDeclKind))
2501+
ERROR(implementation_only_override_import_without_attr,none,
2502+
"override of %0 imported as implementation-only must be declared "
2503+
"'@_implementationOnly'", (DescriptiveDeclKind))
2504+
24932505
// Derived conformances
24942506
ERROR(cannot_synthesize_init_in_extension_of_nonfinal,none,
24952507
"implementation of %0 for non-final class cannot be automatically "

trunk/lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ PrintOptions PrintOptions::printParseableInterfaceFile(bool preferTypeRepr) {
126126

127127
class ShouldPrintForParseableInterface : public ShouldPrintChecker {
128128
bool shouldPrint(const Decl *D, const PrintOptions &options) override {
129+
// Skip anything that is marked `@_implementationOnly` itself.
130+
if (D->getAttrs().hasAttribute<ImplementationOnlyAttr>())
131+
return false;
132+
129133
// Skip anything that isn't 'public' or '@usableFromInline'.
130134
if (auto *VD = dyn_cast<ValueDecl>(D)) {
131135
if (!isPublicOrUsableFromInline(VD)) {

trunk/lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
204204
}
205205

206206
bool shouldInclude(const ValueDecl *VD) {
207-
return isVisibleToObjC(VD, minRequiredAccess);
207+
return isVisibleToObjC(VD, minRequiredAccess) &&
208+
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>();
208209
}
209210

210211
private:

trunk/lib/Sema/TypeCheckAccess.cpp

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,9 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
16521652
explicit ExportabilityChecker(TypeChecker &TC) : TC(TC) {}
16531653

16541654
static bool shouldSkipChecking(const ValueDecl *VD) {
1655+
if (VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
1656+
return true;
1657+
16551658
// Accessors are handled as part of their Var or Subscript, and we don't
16561659
// want to redo extension signature checking for them.
16571660
if (isa<AccessorDecl>(VD))
@@ -1681,13 +1684,49 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
16811684
return true;
16821685
}
16831686

1687+
void checkOverride(const ValueDecl *VD) {
1688+
const ValueDecl *overridden = VD->getOverriddenDecl();
1689+
if (!overridden)
1690+
return;
1691+
1692+
auto *SF = VD->getDeclContext()->getParentSourceFile();
1693+
assert(SF && "checking a non-source declaration?");
1694+
1695+
ModuleDecl *M = overridden->getModuleContext();
1696+
if (SF->isImportedImplementationOnly(M)) {
1697+
TC.diagnose(VD, diag::implementation_only_override_import_without_attr,
1698+
overridden->getDescriptiveKind())
1699+
.fixItInsert(VD->getAttributeInsertionLoc(false),
1700+
"@_implementationOnly ");
1701+
TC.diagnose(overridden, diag::overridden_here);
1702+
return;
1703+
}
1704+
1705+
if (overridden->getAttrs().hasAttribute<ImplementationOnlyAttr>()) {
1706+
TC.diagnose(VD, diag::implementation_only_override_without_attr,
1707+
overridden->getDescriptiveKind())
1708+
.fixItInsert(VD->getAttributeInsertionLoc(false),
1709+
"@_implementationOnly ");
1710+
TC.diagnose(overridden, diag::overridden_here);
1711+
return;
1712+
}
1713+
1714+
// FIXME: Check storage decls where the setter is in a separate module from
1715+
// the getter, which is a thing Objective-C can do. The ClangImporter
1716+
// doesn't make this easy, though, because it just gives the setter the same
1717+
// DeclContext as the property or subscript, which means we've lost the
1718+
// information about whether its module was implementation-only imported.
1719+
}
1720+
16841721
void visit(Decl *D) {
16851722
if (D->isInvalid() || D->isImplicit())
16861723
return;
16871724

1688-
if (auto *VD = dyn_cast<ValueDecl>(D))
1725+
if (auto *VD = dyn_cast<ValueDecl>(D)) {
16891726
if (shouldSkipChecking(VD))
16901727
return;
1728+
checkOverride(VD);
1729+
}
16911730

16921731
DeclVisitor<ExportabilityChecker>::visit(D);
16931732
}
@@ -1729,13 +1768,16 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
17291768
void checkNamedPattern(const NamedPattern *NP,
17301769
const llvm::DenseSet<const VarDecl *> &seenVars) {
17311770
const VarDecl *theVar = NP->getDecl();
1732-
// Only check individual variables if we didn't check an enclosing
1733-
// TypedPattern.
1734-
if (seenVars.count(theVar) || theVar->isInvalid())
1735-
return;
17361771
if (shouldSkipChecking(theVar))
17371772
return;
17381773

1774+
checkOverride(theVar);
1775+
1776+
// Only check the type of individual variables if we didn't check an
1777+
// enclosing TypedPattern.
1778+
if (seenVars.count(theVar) || theVar->isInvalid())
1779+
return;
1780+
17391781
checkType(theVar->getInterfaceType(), /*typeRepr*/nullptr, theVar,
17401782
getDiagnoseCallback(theVar), getDiagnoseCallback(theVar));
17411783
}

trunk/lib/Sema/TypeCheckAttr.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
772772
IGNORED_ATTR(IBDesignable)
773773
IGNORED_ATTR(IBInspectable)
774774
IGNORED_ATTR(IBOutlet) // checked early.
775-
IGNORED_ATTR(ImplementationOnly)
776775
IGNORED_ATTR(ImplicitlyUnwrappedOptional)
777776
IGNORED_ATTR(Indirect)
778777
IGNORED_ATTR(Inline)
@@ -858,6 +857,8 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
858857
void visitCustomAttr(CustomAttr *attr);
859858
void visitPropertyWrapperAttr(PropertyWrapperAttr *attr);
860859
void visitFunctionBuilderAttr(FunctionBuilderAttr *attr);
860+
861+
void visitImplementationOnlyAttr(ImplementationOnlyAttr *attr);
861862
};
862863
} // end anonymous namespace
863864

@@ -2630,6 +2631,69 @@ void AttributeChecker::visitFunctionBuilderAttr(FunctionBuilderAttr *attr) {
26302631
// Any other validation?
26312632
}
26322633

2634+
void
2635+
AttributeChecker::visitImplementationOnlyAttr(ImplementationOnlyAttr *attr) {
2636+
if (isa<ImportDecl>(D)) {
2637+
// These are handled elsewhere.
2638+
return;
2639+
}
2640+
2641+
auto *VD = cast<ValueDecl>(D);
2642+
auto *overridden = VD->getOverriddenDecl();
2643+
if (!overridden) {
2644+
diagnoseAndRemoveAttr(attr, diag::implementation_only_decl_non_override);
2645+
return;
2646+
}
2647+
2648+
// Check if VD has the exact same type as what it overrides.
2649+
// Note: This is specifically not using `swift::getMemberTypeForComparison`
2650+
// because that erases more information than we want, like `throws`-ness.
2651+
auto baseInterfaceTy = overridden->getInterfaceType();
2652+
auto derivedInterfaceTy = VD->getInterfaceType();
2653+
2654+
auto selfInterfaceTy = VD->getDeclContext()->getDeclaredInterfaceType();
2655+
2656+
auto overrideInterfaceTy =
2657+
selfInterfaceTy->adjustSuperclassMemberDeclType(overridden, VD,
2658+
baseInterfaceTy);
2659+
2660+
if (isa<AbstractFunctionDecl>(VD)) {
2661+
// Drop the 'Self' parameter.
2662+
// FIXME: The real effect here, though, is dropping the generic signature.
2663+
// This should be okay because it should already be checked as part of
2664+
// making an override, but that isn't actually the case as of this writing,
2665+
// and it's kind of suspect anyway.
2666+
derivedInterfaceTy =
2667+
derivedInterfaceTy->castTo<AnyFunctionType>()->getResult();
2668+
overrideInterfaceTy =
2669+
overrideInterfaceTy->castTo<AnyFunctionType>()->getResult();
2670+
} else if (isa<SubscriptDecl>(VD)) {
2671+
// For subscripts, we don't have a 'Self' type, but turn it
2672+
// into a monomorphic function type.
2673+
// FIXME: does this actually make sense, though?
2674+
auto derivedInterfaceFuncTy = derivedInterfaceTy->castTo<AnyFunctionType>();
2675+
derivedInterfaceTy =
2676+
FunctionType::get(derivedInterfaceFuncTy->getParams(),
2677+
derivedInterfaceFuncTy->getResult());
2678+
auto overrideInterfaceFuncTy =
2679+
overrideInterfaceTy->castTo<AnyFunctionType>();
2680+
overrideInterfaceTy =
2681+
FunctionType::get(overrideInterfaceFuncTy->getParams(),
2682+
overrideInterfaceFuncTy->getResult());
2683+
}
2684+
2685+
if (!derivedInterfaceTy->isEqual(overrideInterfaceTy)) {
2686+
TC.diagnose(VD, diag::implementation_only_override_changed_type,
2687+
overrideInterfaceTy);
2688+
TC.diagnose(overridden, diag::overridden_here);
2689+
return;
2690+
}
2691+
2692+
// FIXME: When compiling without library evolution enabled, this should also
2693+
// check whether VD or any of its accessors need a new vtable entry, even if
2694+
// it won't necessarily be able to say why.
2695+
}
2696+
26332697
void TypeChecker::checkParameterAttributes(ParameterList *params) {
26342698
for (auto param: *params) {
26352699
checkDeclAttributes(param);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import Foundation;
2+
3+
@interface NSObject (Secrets)
4+
- (void)secretMethod;
5+
@end

trunk/test/PrintAsObjC/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,8 @@ module resilient_objc_class {
4747
header "resilient_objc_class.h"
4848
export *
4949
}
50+
51+
module MiserablePileOfSecrets {
52+
header "MiserablePileOfSecrets.h"
53+
export *
54+
}

trunk/test/PrintAsObjC/imports.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
// CHECK-NEXT: @import MostlyPrivate1;
1818
// CHECK-NEXT: @import MostlyPrivate1_Private;
1919
// CHECK-NEXT: @import MostlyPrivate2_Private;
20+
// CHECK-NEXT: @import ObjectiveC;
2021
// CHECK-NEXT: @import ctypes.bits;
2122

2223
// NEGATIVE-NOT: ctypes;
2324
// NEGATIVE-NOT: ImSub;
2425
// NEGATIVE-NOT: ImplicitSub;
2526
// NEGATIVE-NOT: MostlyPrivate2;
27+
// NEGATIVE-NOT: MiserablePileOfSecrets;
28+
29+
// NEGATIVE-NOT: secretMethod
2630

2731
import ctypes.bits
2832
import Foundation
@@ -40,6 +44,8 @@ import MostlyPrivate1_Private
4044
// Deliberately not importing MostlyPrivate2
4145
import MostlyPrivate2_Private
4246

47+
@_implementationOnly import MiserablePileOfSecrets
48+
4349
@objc class Test {
4450
@objc let word: DWORD = 0
4551
@objc let number: TimeInterval = 0.0
@@ -57,3 +63,7 @@ import MostlyPrivate2_Private
5763

5864
@objc let mp2priv: MP2PrivateType = 0
5965
}
66+
67+
@objc public class TestSubclass: NSObject {
68+
@_implementationOnly public override func secretMethod() {}
69+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@interface Base
2+
@end
3+
4+
@interface Parent : Base
5+
- (nonnull instancetype)init __attribute__((objc_designated_initializer));
6+
7+
// The SECRET is on a non-secret property here because we need to enforce that
8+
// it's not printed.
9+
@property (readonly, strong, nullable) Parent *redefinedPropSECRET;
10+
@end
11+
12+
@interface GenericParent<T: Base *> : Base
13+
- (nonnull instancetype)init __attribute__((objc_designated_initializer));
14+
@end
15+
16+
@interface SubscriptParent : Base
17+
- (nullable Parent *)objectAtIndexedSubscript:(int)index;
18+
@end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#import <FooKit.h>
2+
3+
@interface SECRETType : Base
4+
@end
5+
6+
@interface Parent ()
7+
- (nonnull instancetype)initWithSECRET:(int)secret __attribute__((objc_designated_initializer, swift_name("init(SECRET:)")));
8+
9+
- (void)methodSECRET;
10+
- (nullable SECRETType *)methodWithSECRETType;
11+
12+
@property (readonly, strong, nullable) Parent *roPropSECRET;
13+
@property (readwrite, strong, nullable) Parent *rwPropSECRET;
14+
15+
- (nullable Parent *)objectAtIndexedSubscript:(int)index;
16+
17+
@property (readwrite, strong, nullable) Parent *redefinedPropSECRET;
18+
@end
19+
20+
@protocol MandatorySecrets
21+
- (nonnull instancetype)initWithRequiredSECRET:(int)secret;
22+
@end
23+
24+
@interface Parent () <MandatorySecrets>
25+
- (nonnull instancetype)initWithRequiredSECRET:(int)secret __attribute__((objc_designated_initializer));
26+
@end
27+
28+
@interface GenericParent<T: Base *> ()
29+
@property (readonly, strong, nullable) T roPropSECRET;
30+
- (nullable Parent *)objectAtIndexedSubscript:(int)index;
31+
@end
32+
33+
@interface SubscriptParent ()
34+
- (void)setObject:(nullable Parent *)object atIndexedSubscript:(int)index;
35+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module FooKit {
2+
header "FooKit.h"
3+
export *
4+
}
5+
6+
module FooKit_SECRET {
7+
header "FooKit_SECRET.h"
8+
export *
9+
}

0 commit comments

Comments
 (0)