Skip to content

Commit 0db8bbd

Browse files
authored
Merge pull request #26159 from slavapestov/do-not-finalize-structs-and-enums
Struct and enum declarations no longer go through finalizeDecl()
2 parents ca798ab + 84b0267 commit 0db8bbd

26 files changed

+104
-86
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5823,14 +5823,7 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
58235823
for (auto elt : theEnum->getAllElements()) {
58245824
numElements++;
58255825

5826-
// Compute whether this gives us an apparent payload or dynamic layout.
5827-
// Note that we do *not* apply substitutions from a bound generic instance
5828-
// yet. We want all instances of a generic enum to share an implementation
5829-
// strategy. If the abstract layout of the enum is dependent on generic
5830-
// parameters, then we additionally need to constrain any layout
5831-
// optimizations we perform to things that are reproducible by the runtime.
5832-
Type origArgType = elt->getArgumentInterfaceType();
5833-
if (origArgType.isNull()) {
5826+
if (!elt->hasAssociatedValues()) {
58345827
elementsWithNoPayload.push_back({elt, nullptr, nullptr});
58355828
continue;
58365829
}
@@ -5843,6 +5836,13 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
58435836
continue;
58445837
}
58455838

5839+
// Compute whether this gives us an apparent payload or dynamic layout.
5840+
// Note that we do *not* apply substitutions from a bound generic instance
5841+
// yet. We want all instances of a generic enum to share an implementation
5842+
// strategy. If the abstract layout of the enum is dependent on generic
5843+
// parameters, then we additionally need to constrain any layout
5844+
// optimizations we perform to things that are reproducible by the runtime.
5845+
Type origArgType = elt->getArgumentInterfaceType();
58465846
origArgType = theEnum->mapTypeIntoContext(origArgType);
58475847

58485848
auto origArgLoweredTy = TC.IGM.getLoweredType(origArgType);

lib/SIL/TypeLowering.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ namespace {
237237
llvm_unreachable("shouldn't get an inout type here");
238238
}
239239
RetTy visitErrorType(CanErrorType type) {
240-
llvm_unreachable("shouldn't get an error type here");
240+
return asImpl().handleTrivial(type);
241241
}
242242

243243
// Dependent types should be contextualized before visiting.
@@ -501,9 +501,6 @@ namespace {
501501
static RecursiveProperties classifyType(CanType type, SILModule &M,
502502
CanGenericSignature sig,
503503
ResilienceExpansion expansion) {
504-
assert(!type->hasError() &&
505-
"Error types should not appear in type-checked AST");
506-
507504
return TypeClassifier(M, sig, expansion).visit(type);
508505
}
509506

@@ -1559,9 +1556,6 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
15591556

15601557
CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType,
15611558
CanType substType) {
1562-
assert(!substType->hasError() &&
1563-
"Error types should not appear in type-checked AST");
1564-
15651559
// AST function types are turned into SIL function types:
15661560
// - the type is uncurried as desired
15671561
// - types are turned into their unbridged equivalents, depending

lib/Sema/CodeSynthesis.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,6 @@ void swift::triggerAccessorSynthesis(TypeChecker &TC,
20122012
if (!accessor->hasBody()) {
20132013
maybeMarkTransparent(accessor, TC.Context);
20142014
accessor->setBodySynthesizer(&synthesizeAccessorBody);
2015-
TC.DeclsToFinalize.insert(accessor);
20162015
}
20172016
});
20182017
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,7 +2319,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23192319
(void) VD->isDynamic();
23202320

23212321
// Make sure we finalize this declaration.
2322-
TC.DeclsToFinalize.insert(VD);
2322+
if (isa<ClassDecl>(VD) || isa<ProtocolDecl>(VD) ||
2323+
isa<AbstractStorageDecl>(VD))
2324+
TC.DeclsToFinalize.insert(VD);
23232325

23242326
// If this is a member of a nominal type, don't allow it to have a name of
23252327
// "Type" or "Protocol" since we reserve the X.Type and X.Protocol
@@ -2873,11 +2875,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
28732875
TC.validateDecl(SD);
28742876
checkGenericParams(SD->getGenericParams(), SD, TC);
28752877

2876-
TC.addImplicitConstructors(SD);
2877-
28782878
// Force lowering of stored properties.
28792879
(void) SD->getStoredProperties();
28802880

2881+
TC.addImplicitConstructors(SD);
2882+
28812883
for (Decl *Member : SD->getMembers())
28822884
visit(Member);
28832885

@@ -3008,9 +3010,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30083010
// Force lowering of stored properties.
30093011
(void) CD->getStoredProperties();
30103012

3011-
for (Decl *Member : CD->getMembers()) {
3013+
TC.addImplicitConstructors(CD);
3014+
CD->addImplicitDestructor();
3015+
3016+
for (Decl *Member : CD->getMembers())
30123017
visit(Member);
3013-
}
30143018

30153019
TC.checkPatternBindingCaptures(CD);
30163020

@@ -3019,9 +3023,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30193023
if (CD->requiresStoredPropertyInits())
30203024
checkRequiredInClassInits(CD);
30213025

3022-
TC.addImplicitConstructors(CD);
3023-
CD->addImplicitDestructor();
3024-
30253026
// Compute @objc for each superclass member, to catch selector
30263027
// conflicts resulting from unintended overrides.
30273028
//
@@ -3913,9 +3914,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
39133914
checkEnumRawValues(*this, ED);
39143915
}
39153916

3916-
if (!isa<ClassDecl>(nominal))
3917-
requestNominalLayout(nominal);
3918-
39193917
break;
39203918
}
39213919

@@ -4457,38 +4455,6 @@ void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
44574455
}
44584456
}
44594457

4460-
static bool shouldValidateMemberDuringFinalization(NominalTypeDecl *nominal,
4461-
ValueDecl *VD) {
4462-
// For enums, we only need to validate enum elements to know
4463-
// the layout.
4464-
if (isa<EnumDecl>(nominal) &&
4465-
isa<EnumElementDecl>(VD))
4466-
return true;
4467-
4468-
// For structs, we only need to validate stored properties to
4469-
// know the layout.
4470-
if (isa<StructDecl>(nominal) &&
4471-
(isa<VarDecl>(VD) &&
4472-
!cast<VarDecl>(VD)->isStatic() &&
4473-
(cast<VarDecl>(VD)->hasStorage() ||
4474-
VD->getAttrs().hasAttribute<LazyAttr>() ||
4475-
cast<VarDecl>(VD)->hasAttachedPropertyWrapper())))
4476-
return true;
4477-
4478-
// For classes, we need to validate properties and functions,
4479-
// but skipping nested types is OK.
4480-
if (isa<ClassDecl>(nominal) &&
4481-
!isa<TypeDecl>(VD))
4482-
return true;
4483-
4484-
// For protocols, skip nested typealiases and nominal types.
4485-
if (isa<ProtocolDecl>(nominal) &&
4486-
!isa<GenericTypeDecl>(VD))
4487-
return true;
4488-
4489-
return false;
4490-
}
4491-
44924458
void TypeChecker::requestMemberLayout(ValueDecl *member) {
44934459
auto *dc = member->getDeclContext();
44944460
if (auto *classDecl = dyn_cast<ClassDecl>(dc))
@@ -4531,13 +4497,11 @@ static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) {
45314497
// Force lowering of stored properties.
45324498
(void) nominal->getStoredProperties();
45334499

4534-
for (auto *D : nominal->getMembers()) {
4535-
auto VD = dyn_cast<ValueDecl>(D);
4536-
if (!VD)
4537-
continue;
4538-
4539-
if (shouldValidateMemberDuringFinalization(nominal, VD))
4540-
TC.DeclsToFinalize.insert(VD);
4500+
if (isa<ClassDecl>(nominal) || isa<ProtocolDecl>(nominal)) {
4501+
for (auto *D : nominal->getMembers()) {
4502+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(D))
4503+
TC.DeclsToFinalize.insert(ASD);
4504+
}
45414505
}
45424506

45434507
if (auto *CD = dyn_cast<ClassDecl>(nominal)) {

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3703,7 +3703,8 @@ void ConformanceChecker::resolveValueWitnesses() {
37033703

37043704
// Make sure that we finalize the witness, so we can emit this
37053705
// witness table.
3706-
TC.DeclsToFinalize.insert(witness);
3706+
if (isa<AbstractStorageDecl>(witness))
3707+
TC.DeclsToFinalize.insert(witness);
37073708

37083709
// Objective-C checking for @objc requirements.
37093710
if (requirement->isObjC() &&

test/decl/class/override.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@ class Base24646184 {
265265
func foo(ok: SubTy) { }
266266
}
267267
class Derived24646184 : Base24646184 {
268-
override init(_: Ty) { } // expected-note {{'init(_:)' previously overridden here}}
269-
override init(_: SubTy) { } // expected-error {{'init(_:)' has already been overridden}}
268+
override init(_: Ty) { } // expected-error {{'init(_:)' has already been overridden}}
269+
override init(_: SubTy) { } // expected-note {{'init(_:)' previously overridden here}}
270270
override func foo(_: Ty) { } // expected-note {{'foo' previously overridden here}}
271271
override func foo(_: SubTy) { } // expected-error {{'foo' has already been overridden}}
272272

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
struct S {
2-
var a = S() // expected-error {{'S' cannot be constructed because it has no accessible initializers}}
2+
var a = S()
33
}

test/decl/init/basic_init.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@ class InitClass {
2323
@objc dynamic init(bar: Int) {}
2424
}
2525
class InitSubclass: InitClass {}
26-
// expected-note@-1 {{'init(bar:)' previously overridden here}}
27-
// expected-note@-2 {{'init(baz:)' previously overridden here}}
26+
// expected-error@-1 {{'init(bar:)' has already been overridden}}
27+
// expected-error@-2 {{'init(baz:)' has already been overridden}}
2828
extension InitSubclass {
2929
convenience init(arg: Bool) {} // expected-error{{overriding non-@objc declarations from extensions is not supported}}
30-
convenience override init(baz: Int) {}
30+
convenience override init(baz: Int) {} // expected-note{{'init(baz:)' previously overridden here}}
3131
// expected-error@-1 {{cannot override a non-dynamic class declaration from an extension}}
32-
// expected-error@-2 {{'init(baz:)' has already been overridden}}
33-
convenience override init(bar: Int) {} // expected-error{{'init(bar:)' has already been overridden}}
32+
convenience override init(bar: Int) {} // expected-note{{'init(bar:)' previously overridden here}}
3433
}
3534

3635
struct InitStruct {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
public indirect enum E {
2+
case foo(Any)
3+
case bar(EE)
4+
case blah
5+
}
6+
7+
public enum EE {
8+
case x(Int)
9+
case y(String)
10+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public struct S {
2+
var x: DoesNotExist // expected-error {{use of undeclared type 'DoesNotExist'}}
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: %target-swift-frontend -emit-ir -primary-file %s %S/Inputs/require-layout-enum-other.swift -module-name layout
2+
3+
public func returnE() -> E { return .blah }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: %target-swift-frontend -verify -emit-ir -primary-file %s %S/Inputs/require-layout-error-other.swift -module-name layout
2+
3+
public func identity(_ s: S) -> S { return s }

validation-test/compiler_crashers_2_fixed/0124-sr5825.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: not %target-swift-frontend %s -emit-ir
1+
// RUN: %target-swift-frontend %s -emit-ir
22

33
struct DefaultAssociatedType {
44
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend -emit-ir -primary-file %s %S/Inputs/sr9583-other.swift -module-name foo
2+
3+
protocol P {
4+
associatedtype A
5+
typealias T = S1<Self>
6+
}
7+
8+
struct S1<G: P>: Sequence, IteratorProtocol {
9+
mutating func next() -> G.A? {
10+
return nil
11+
}
12+
}
13+
14+
func f(_: LazyFilterSequence<S3.T>) { }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
struct S2 {
2+
let v: Int
3+
}
4+
5+
struct S3: P {
6+
typealias A = S2
7+
}

validation-test/compiler_scale/bind_extension_decl.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

validation-test/compiler_scale/bind_nested_extension_decl.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

validation-test/compiler_scale/class_members.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
2+
// REQUIRES: OS=macosx
3+
// REQUIRES: asserts
4+
5+
indirect enum Enum${N} {
6+
case OK
7+
8+
% if int(N) > 1:
9+
case next(Enum${int(N)-1})
10+
% end
11+
}

validation-test/compiler_scale/enum_members.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

validation-test/compiler_scale/function_bodies.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumFunctionsParsed %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumFunctionsParsed %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

@@ -34,4 +34,4 @@ protocol P${N} {
3434

3535
extension P${N} {
3636
func otherMethod${N}() {}
37-
}
37+
}

validation-test/compiler_scale/protocol_members.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

validation-test/compiler_scale/scale_neighbouring_getset.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumFunctionsTypechecked %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumFunctionsTypechecked %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

validation-test/compiler_scale/struct_members.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
2+
// REQUIRES: OS=macosx
3+
// REQUIRES: asserts
4+
5+
struct Struct${N} {
6+
% if int(N) > 1:
7+
var next: Struct${int(N)-1}.Nested? = nil
8+
% end
9+
struct Nested {}
10+
}

validation-test/compiler_scale/used_conformances.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --sum-multi --typecheck --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
1+
// RUN: %scale-test --sum-multi --begin 5 --end 16 --step 5 --select NumDeclsValidated %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

0 commit comments

Comments
 (0)