Skip to content

Commit 4096000

Browse files
authored
Merge pull request swiftlang#12942 from slavapestov/lazy-protocol-member-validation
Lazy protocol member validation
2 parents 3f7d7c2 + 772bd76 commit 4096000

File tree

14 files changed

+101
-53
lines changed

14 files changed

+101
-53
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,9 +1028,9 @@ ERROR(static_functions_not_mutating,none,
10281028
"static functions must not be declared mutating", ())
10291029

10301030
ERROR(transparent_in_protocols_not_supported,none,
1031-
"@_transparent is not supported on declarations within protocols", ())
1031+
"'@_transparent' attribute is not supported on declarations within protocols", ())
10321032
ERROR(transparent_in_classes_not_supported,none,
1033-
"@_transparent is not supported on declarations within classes", ())
1033+
"'@_transparent' attribute is not supported on declarations within classes", ())
10341034

10351035
ERROR(invalid_iboutlet,none,
10361036
"only instance properties can be declared @IBOutlet", ())
@@ -1124,7 +1124,7 @@ ERROR(access_control_open_bad_decl,none,
11241124
ERROR(invalid_decl_attribute_simple,none,
11251125
"attribute cannot be applied to declaration", ())
11261126
ERROR(invalid_decl_attribute,none,
1127-
"%0 cannot be applied to this declaration", (DeclAttribute))
1127+
"'%0' attribute cannot be applied to this declaration", (DeclAttribute))
11281128
ERROR(invalid_decl_modifier,none,
11291129
"%0 modifier cannot be applied to this declaration", (DeclAttribute))
11301130
ERROR(attribute_does_not_apply_to_type,none,
@@ -3707,7 +3707,7 @@ ERROR(class_designated_init_inlineable_resilient,none,
37073707
"delegate to another initializer", (Type, unsigned))
37083708

37093709
ERROR(attribute_invalid_on_stored_property,
3710-
none, "@%0 cannot be applied to stored properties", (StringRef))
3710+
none, "'@%0' attribute cannot be applied to stored properties", (StringRef))
37113711

37123712
ERROR(inlineable_dynamic_not_supported,
37133713
none, "'@_inlineable' attribute cannot be applied to 'dynamic' declarations", ())

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,9 @@ namespace {
849849
// Class members might be virtually dispatched, so we need to know
850850
// the full layout of the class.
851851
if (auto *classDecl = dyn_cast<ClassDecl>(member->getDeclContext()))
852-
tc.requestClassLayout(classDecl);
852+
tc.requestNominalLayout(classDecl);
853+
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(member->getDeclContext()))
854+
tc.requestNominalLayout(protocolDecl);
853855

854856
auto refTy = solution.simplifyType(openedFullType);
855857

lib/Sema/TypeCheckDecl.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6906,6 +6906,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
69066906
if (auto extendedTy = ED->getExtendedType()) {
69076907
if (auto nominal = extendedTy->getAnyNominal()) {
69086908
TC.validateDecl(nominal);
6909+
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
6910+
TC.requestNominalLayout(classDecl);
6911+
69096912
// Check the raw values of an enum, since we might synthesize
69106913
// RawRepresentable while checking conformances on this extension.
69116914
if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
@@ -7608,7 +7611,14 @@ void TypeChecker::validateDecl(ValueDecl *D) {
76087611
markAsObjC(*this, proto, isObjC);
76097612
}
76107613

7611-
DeclsToFinalize.insert(proto);
7614+
// FIXME: IRGen likes to emit @objc protocol descriptors even if the
7615+
// protocol comes from a different module or translation unit.
7616+
//
7617+
// It would be nice if it didn't have to do that, then we could remove
7618+
// this case.
7619+
if (proto->isObjC())
7620+
requestNominalLayout(proto);
7621+
76127622
break;
76137623
}
76147624

@@ -7794,8 +7804,17 @@ void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
77947804
validateDeclForNameLookup(ATD);
77957805
}
77967806

7797-
// Make sure the protocol is fully validated by the end of Sema.
7798-
DeclsToFinalize.insert(proto);
7807+
// Compute the requirement signature later to avoid circularity.
7808+
DelayedRequirementSignatures.insert(proto);
7809+
7810+
// FIXME: IRGen likes to emit @objc protocol descriptors even if the
7811+
// protocol comes from a different module or translation unit.
7812+
//
7813+
// It would be nice if it didn't have to do that, then we could remove
7814+
// this case.
7815+
if (proto->isObjC())
7816+
requestNominalLayout(proto);
7817+
77997818
break;
78007819
}
78017820
case DeclKind::AssociatedType: {
@@ -7885,22 +7904,22 @@ static bool shouldValidateMemberDuringFinalization(NominalTypeDecl *nominal,
78857904
return false;
78867905
}
78877906

7888-
void TypeChecker::requestClassLayout(ClassDecl *classDecl) {
7889-
if (classDecl->hasValidatedLayout())
7907+
void TypeChecker::requestNominalLayout(NominalTypeDecl *nominalDecl) {
7908+
if (nominalDecl->hasValidatedLayout())
78907909
return;
78917910

7892-
classDecl->setHasValidatedLayout();
7911+
nominalDecl->setHasValidatedLayout();
78937912

7894-
if (isa<SourceFile>(classDecl->getModuleScopeContext()))
7895-
DeclsToFinalize.insert(classDecl);
7913+
if (isa<SourceFile>(nominalDecl->getModuleScopeContext()))
7914+
DeclsToFinalize.insert(nominalDecl);
78967915
}
78977916

78987917
void TypeChecker::requestSuperclassLayout(ClassDecl *classDecl) {
78997918
auto superclassTy = classDecl->getSuperclass();
79007919
if (superclassTy) {
79017920
auto *superclassDecl = superclassTy->getClassOrBoundGenericClass();
79027921
if (superclassDecl)
7903-
requestClassLayout(superclassDecl);
7922+
requestNominalLayout(superclassDecl);
79047923
}
79057924
}
79067925

@@ -8180,8 +8199,6 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
81808199
// Validate the nominal type declaration being extended.
81818200
auto nominal = extendedType->getAnyNominal();
81828201
validateDecl(nominal);
8183-
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
8184-
requestClassLayout(classDecl);
81858202

81868203
if (nominal->getGenericParamsOfContext()) {
81878204
auto genericParams = ext->getGenericParams();

lib/Sema/TypeChecker.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,16 @@ static void typeCheckFunctionsAndExternalDecls(TypeChecker &TC) {
447447
llvm_unreachable("Unhandled external definition kind");
448448
}
449449

450+
// Complete any protocol requirement signatures that were delayed
451+
// because the protocol was validated via validateDeclForNameLookup().
452+
while (!TC.DelayedRequirementSignatures.empty()) {
453+
auto decl = TC.DelayedRequirementSignatures.pop_back_val();
454+
if (decl->isInvalid() || TC.Context.hadError())
455+
continue;
456+
457+
TC.validateDecl(decl);
458+
}
459+
450460
// Validate any referenced declarations for SIL's purposes.
451461
// Note: if we ever start putting extension members in vtables, we'll need
452462
// to validate those members too.
@@ -470,6 +480,7 @@ static void typeCheckFunctionsAndExternalDecls(TypeChecker &TC) {
470480
} while (currentFunctionIdx < TC.definedFunctions.size() ||
471481
currentExternalDef < TC.Context.ExternalDefinitions.size() ||
472482
!TC.DeclsToFinalize.empty() ||
483+
!TC.DelayedRequirementSignatures.empty() ||
473484
!TC.UsedConformances.empty());
474485

475486
// FIXME: Horrible hack. Store this somewhere more appropriate.

lib/Sema/TypeChecker.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,11 @@ class TypeChecker final : public LazyResolver {
715715
/// we can hand them off to SILGen etc.
716716
llvm::SetVector<ValueDecl *> DeclsToFinalize;
717717

718+
/// The list of protocols that need their requirement signatures computed,
719+
/// because they were first validated by validateDeclForNameLookup(),
720+
/// which skips this step.
721+
llvm::SetVector<ProtocolDecl *> DelayedRequirementSignatures;
722+
718723
/// The list of types whose circularity checks were delayed.
719724
SmallVector<NominalTypeDecl*, 8> DelayedCircularityChecks;
720725

@@ -1068,7 +1073,7 @@ class TypeChecker final : public LazyResolver {
10681073

10691074
/// Request that the given class needs to have all members validated
10701075
/// after everything in the translation unit has been processed.
1071-
void requestClassLayout(ClassDecl *classDecl);
1076+
void requestNominalLayout(NominalTypeDecl *nominalDecl);
10721077

10731078
/// Request that the superclass of the given class, if any, needs to have
10741079
/// all members validated after everything in the translation unit has

test/attr/attr_inlineable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-testing
33

44
@_inlineable struct TestInlineableStruct {}
5-
// expected-error@-1 {{@_inlineable cannot be applied to this declaration}}
5+
// expected-error@-1 {{'@_inlineable' attribute cannot be applied to this declaration}}
66

77
private func privateFunction() {}
88
// expected-note@-1{{global function 'privateFunction()' is not '@_versioned' or public}}
@@ -24,10 +24,10 @@ public struct PublicStruct {
2424
public init() {}
2525

2626
@_inlineable public var storedProperty: Int
27-
// expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
27+
// expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
2828

2929
@_inlineable public lazy var lazyProperty: Int = 0
30-
// expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
30+
// expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
3131
}
3232

3333
public struct Struct {

test/attr/attr_nonobjc.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ class BlueLightSaber : LightSaber {
3939
init(x: String) {} // expected-error {{conflicts with previous declaration with the same Objective-C selector}}
4040
}
4141

42-
@nonobjc class NonObjCClassNotAllowed { } // expected-error {{@nonobjc cannot be applied to this declaration}} {{1-10=}}
42+
@nonobjc class NonObjCClassNotAllowed { } // expected-error {{'@nonobjc' attribute cannot be applied to this declaration}} {{1-10=}}
4343

4444
class NonObjCDeallocNotAllowed {
45-
@nonobjc deinit { // expected-error {{@nonobjc cannot be applied to this declaration}} {{3-12=}}
45+
@nonobjc deinit { // expected-error {{'@nonobjc' attribute cannot be applied to this declaration}} {{3-12=}}
4646

4747
}
4848
}

test/attr/attr_objc.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func subject_genericFunc<T>(t: T) { // expected-error {{@objc can only be used w
121121
func subject_funcParam(a: @objc Int) { // expected-error {{attribute can only be applied to declarations, not types}} {{1-1=@objc }} {{27-33=}}
122122
}
123123

124-
@objc // expected-error {{@objc cannot be applied to this declaration}} {{1-7=}}
124+
@objc // expected-error {{'@objc' attribute cannot be applied to this declaration}} {{1-7=}}
125125
struct subject_struct {
126126
@objc
127127
var subject_instanceVar: Int // expected-error {{@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes}} {{3-8=}}
@@ -133,7 +133,7 @@ struct subject_struct {
133133
func subject_instanceFunc() {} // expected-error {{@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes}} {{3-8=}}
134134
}
135135

136-
@objc // expected-error {{@objc cannot be applied to this declaration}} {{1-7=}}
136+
@objc // expected-error {{'@objc' attribute cannot be applied to this declaration}} {{1-7=}}
137137
struct subject_genericStruct<T> {
138138
@objc
139139
var subject_instanceVar: Int // expected-error {{@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes}} {{3-8=}}
@@ -209,7 +209,7 @@ enum subject_enum: Int {
209209
@objc // expected-error {{attribute has no effect; cases within an '@objc' enum are already exposed to Objective-C}} {{3-9=}}
210210
case subject_enumElement5, subject_enumElement6
211211

212-
@nonobjc // expected-error {{@nonobjc cannot be applied to this declaration}}
212+
@nonobjc // expected-error {{'@nonobjc' attribute cannot be applied to this declaration}}
213213
case subject_enumElement7
214214

215215
@objc

test/attr/attr_versioned.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fileprivate class filePrivateClass {
3131
}
3232

3333
@_versioned extension S {}
34-
// expected-error@-1 {{@_versioned cannot be applied to this declaration}}
34+
// expected-error@-1 {{'@_versioned' attribute cannot be applied to this declaration}}
3535

3636
@_versioned
3737
protocol VersionedProtocol {

test/attr/attributes.swift

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ func f5(x: inout binary) {}
1717

1818
@IBDesignable
1919
class IBDesignableClassTy {
20-
@IBDesignable func foo() {} // expected-error {{@IBDesignable cannot be applied to this declaration}} {{3-17=}}
20+
@IBDesignable func foo() {} // expected-error {{'@IBDesignable' attribute cannot be applied to this declaration}} {{3-17=}}
2121
}
2222

23-
@IBDesignable // expected-error {{@IBDesignable cannot be applied to this declaration}} {{1-15=}}
23+
@IBDesignable // expected-error {{'@IBDesignable' attribute cannot be applied to this declaration}} {{1-15=}}
2424
struct IBDesignableStructTy {}
2525

26-
@IBDesignable // expected-error {{@IBDesignable cannot be applied to this declaration}} {{1-15=}}
26+
@IBDesignable // expected-error {{'@IBDesignable' attribute cannot be applied to this declaration}} {{1-15=}}
2727
protocol IBDesignableProtTy {}
2828

2929
@IBDesignable // expected-error {{@IBDesignable can only be applied to classes and extensions of classes}} {{1-15=}}
@@ -54,21 +54,21 @@ func foo(x: @convention(block) (Int) -> Int) {}
5454
func zim() {}
5555
@_transparent
5656
func zung<T>(_: T) {}
57-
@_transparent // expected-error{{@_transparent cannot be applied to stored properties}} {{1-15=}}
57+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to stored properties}} {{1-15=}}
5858
var zippity : Int
5959
func zoom(x: @_transparent () -> ()) { } // expected-error{{attribute can only be applied to declarations, not types}} {{1-1=@_transparent }} {{14-28=}}
6060
protocol ProtoWithTransparent {
61-
@_transparent// expected-error{{@_transparent is not supported on declarations within protocols}} {{3-16=}}
61+
@_transparent// expected-error{{'@_transparent' attribute is not supported on declarations within protocols}} {{3-16=}}
6262
func transInProto()
6363
}
6464
class TestTranspClass : ProtoWithTransparent {
65-
@_transparent // expected-error{{@_transparent is not supported on declarations within classes}} {{3-17=}}
65+
@_transparent // expected-error{{'@_transparent' attribute is not supported on declarations within classes}} {{3-17=}}
6666
init () {}
67-
@_transparent // expected-error{{@_transparent cannot be applied to this declaration}} {{3-17=}}
67+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to this declaration}} {{3-17=}}
6868
deinit {}
69-
@_transparent // expected-error{{@_transparent is not supported on declarations within classes}} {{3-17=}}
69+
@_transparent // expected-error{{'@_transparent' attribute is not supported on declarations within classes}} {{3-17=}}
7070
class func transStatic() {}
71-
@_transparent// expected-error{{@_transparent is not supported on declarations within classes}} {{3-16=}}
71+
@_transparent// expected-error{{'@_transparent' attribute is not supported on declarations within classes}} {{3-16=}}
7272
func transInProto() {}
7373
}
7474
struct TestTranspStruct : ProtoWithTransparent{
@@ -81,33 +81,33 @@ struct TestTranspStruct : ProtoWithTransparent{
8181
@_transparent
8282
func transInProto() {}
8383
}
84-
@_transparent // expected-error{{@_transparent cannot be applied to this declaration}} {{1-15=}}
84+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to this declaration}} {{1-15=}}
8585
struct CannotHaveTransparentStruct {
8686
func m1() {}
8787
}
88-
@_transparent // expected-error{{@_transparent cannot be applied to this declaration}} {{1-15=}}
88+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to this declaration}} {{1-15=}}
8989
extension TestTranspClass {
9090
func tr1() {}
9191
}
92-
@_transparent // expected-error{{@_transparent cannot be applied to this declaration}} {{1-15=}}
92+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to this declaration}} {{1-15=}}
9393
extension TestTranspStruct {
9494
func tr1() {}
9595
}
96-
@_transparent // expected-error{{@_transparent cannot be applied to this declaration}} {{1-15=}}
96+
@_transparent // expected-error{{'@_transparent' attribute cannot be applied to this declaration}} {{1-15=}}
9797
extension binary {
9898
func tr1() {}
9999
}
100100

101101
class transparentOnClassVar {
102-
@_transparent var max: Int { return 0xFF }; // expected-error {{@_transparent is not supported on declarations within classes}} {{3-17=}}
102+
@_transparent var max: Int { return 0xFF }; // expected-error {{'@_transparent' attribute is not supported on declarations within classes}} {{3-17=}}
103103
func blah () {
104104
var _: Int = max
105105
}
106106
};
107107

108108
class transparentOnClassVar2 {
109109
var max: Int {
110-
@_transparent // expected-error {{@_transparent is not supported on declarations within classes}} {{5-19=}}
110+
@_transparent // expected-error {{'@_transparent' attribute is not supported on declarations within classes}} {{5-19=}}
111111
get {
112112
return 0xFF
113113
}
@@ -206,18 +206,18 @@ func func_type_attribute_with_space(x: @convention (c) () -> Int) {} // OK. Know
206206
var thinFunc : @thin () -> () // expected-error {{attribute is not supported}}
207207

208208
@inline(never) func nolineFunc() {}
209-
@inline(never) var noinlineVar : Int // expected-error {{@inline(never) cannot be applied to this declaration}} {{1-16=}}
210-
@inline(never) class FooClass { // expected-error {{@inline(never) cannot be applied to this declaration}} {{1-16=}}
209+
@inline(never) var noinlineVar : Int // expected-error {{'@inline(never)' attribute cannot be applied to this declaration}} {{1-16=}}
210+
@inline(never) class FooClass { // expected-error {{'@inline(never)' attribute cannot be applied to this declaration}} {{1-16=}}
211211
}
212212

213213
@inline(__always) func AlwaysInlineFunc() {}
214-
@inline(__always) var alwaysInlineVar : Int // expected-error {{@inline(__always) cannot be applied to this declaration}} {{1-19=}}
215-
@inline(__always) class FooClass2 { // expected-error {{@inline(__always) cannot be applied to this declaration}} {{1-19=}}
214+
@inline(__always) var alwaysInlineVar : Int // expected-error {{'@inline(__always)' attribute cannot be applied to this declaration}} {{1-19=}}
215+
@inline(__always) class FooClass2 { // expected-error {{'@inline(__always)' attribute cannot be applied to this declaration}} {{1-19=}}
216216
}
217217

218218
@_optimize(speed) func OspeedFunc() {}
219-
@_optimize(speed) var OpeedVar : Int // expected-error {{@_optimize(speed) cannot be applied to stored properties}} {{1-19=}}
220-
@_optimize(speed) class OspeedClass { // expected-error {{@_optimize(speed) cannot be applied to this declaration}} {{1-19=}}
219+
@_optimize(speed) var OpeedVar : Int // expected-error {{'@_optimize(speed)' attribute cannot be applied to stored properties}} {{1-19=}}
220+
@_optimize(speed) class OspeedClass { // expected-error {{'@_optimize(speed)' attribute cannot be applied to this declaration}} {{1-19=}}
221221
}
222222

223223
class A {
@@ -251,7 +251,7 @@ class C {
251251
@_optimize(size) set {
252252
}
253253
}
254-
@_optimize(size) var c : Int // expected-error {{@_optimize(size) cannot be applied to stored properties}}
254+
@_optimize(size) var c : Int // expected-error {{'@_optimize(size)' attribute cannot be applied to stored properties}}
255255
}
256256

257257
class SILStored {

0 commit comments

Comments
 (0)