From da591acbca8476889806c326d9f78121c93dc51c Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Wed, 13 Jun 2018 15:01:36 -0700 Subject: [PATCH] Sema: Make implicit elementwise struct init insensitive to lazy validation order. With batch mode, other files may have forced lazy properties to get finalized before the implicit constructor is formed. Avoid the order dependency by making the behavior stable regardless of the type-checking phase of lazy declarations. Fixes rdar://problem/40903186. --- lib/Sema/CodeSynthesis.cpp | 17 +++++++++++++---- .../Inputs/lazy_properties_batch_mode_b.swift | 7 +++++++ test/decl/var/lazy_properties_batch_mode.swift | 4 ++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 test/decl/var/Inputs/lazy_properties_batch_mode_b.swift create mode 100644 test/decl/var/lazy_properties_batch_mode.swift diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index f172ef89cdbd6..8b202da0b6761 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1881,12 +1881,21 @@ ConstructorDecl *swift::createImplicitConstructor(TypeChecker &tc, if (ICK == ImplicitConstructorKind::Memberwise) { assert(isa(decl) && "Only struct have memberwise constructor"); - // Computed and static properties are not initialized. - for (auto var : decl->getStoredProperties()) { - if (var->isImplicit()) + for (auto member : decl->getMembers()) { + auto var = dyn_cast(member); + if (!var) continue; - tc.validateDecl(var); + // Implicit, computed, and static properties are not initialized. + // The exception is lazy properties, which due to batch mode we may or + // may not have yet finalized, so they may currently be "stored" or + // "computed" in the current AST state. + if (var->isImplicit() || var->isStatic()) + continue; + tc.validateDecl(var); + if (!var->hasStorage() && !var->getAttrs().hasAttribute()) + continue; + // Initialized 'let' properties have storage, but don't get an argument // to the memberwise initializer since they already have an initial // value that cannot be overridden. diff --git a/test/decl/var/Inputs/lazy_properties_batch_mode_b.swift b/test/decl/var/Inputs/lazy_properties_batch_mode_b.swift new file mode 100644 index 0000000000000..b8fcbf55387c9 --- /dev/null +++ b/test/decl/var/Inputs/lazy_properties_batch_mode_b.swift @@ -0,0 +1,7 @@ +struct B { + var other: Int = 0 + lazy var crash: String = { + return "" + }() +} + diff --git a/test/decl/var/lazy_properties_batch_mode.swift b/test/decl/var/lazy_properties_batch_mode.swift new file mode 100644 index 0000000000000..68957a1db7258 --- /dev/null +++ b/test/decl/var/lazy_properties_batch_mode.swift @@ -0,0 +1,4 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -c -primary-file %s -o %t/a.o -primary-file %S/Inputs/lazy_properties_batch_mode_b.swift -o %t/b.o +func foo(_: B) {} +