@@ -4990,6 +4990,31 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc,
4990
4990
}
4991
4991
}
4992
4992
4993
+ // Lazily construct a mapping from backing storage properties to the
4994
+ // declared properties.
4995
+ bool computedBackingToOriginalVars = false;
4996
+ llvm::SmallDenseMap<VarDecl *, VarDecl *> backingToOriginalVars;
4997
+ auto getOriginalVar = [&](VarDecl *var) -> VarDecl * {
4998
+ // If we haven't computed the mapping yet, do so now.
4999
+ if (!computedBackingToOriginalVars) {
5000
+ for (auto member : classDecl->getMembers()) {
5001
+ if (auto var = dyn_cast<VarDecl>(member)) {
5002
+ if (auto backingVar = var->getPropertyDelegateBackingProperty()) {
5003
+ backingToOriginalVars[backingVar] = var;
5004
+ }
5005
+ }
5006
+ }
5007
+
5008
+ computedBackingToOriginalVars = true;
5009
+ }
5010
+
5011
+ auto known = backingToOriginalVars.find(var);
5012
+ if (known == backingToOriginalVars.end())
5013
+ return nullptr;
5014
+
5015
+ return known->second;
5016
+ };
5017
+
4993
5018
for (auto member : classDecl->getMembers()) {
4994
5019
auto pbd = dyn_cast<PatternBindingDecl>(member);
4995
5020
if (!pbd)
@@ -5000,12 +5025,19 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc,
5000
5025
continue;
5001
5026
5002
5027
for (auto entry : pbd->getPatternList()) {
5003
- if (entry.getInit ()) continue;
5028
+ if (entry.isInitialized ()) continue;
5004
5029
5005
5030
SmallVector<VarDecl *, 4> vars;
5006
5031
entry.getPattern()->collectVariables(vars);
5007
5032
if (vars.empty()) continue;
5008
5033
5034
+ // Replace the variables we found with the originals for diagnostic
5035
+ // purposes.
5036
+ for (auto &var : vars) {
5037
+ if (auto originalVar = getOriginalVar(var))
5038
+ var = originalVar;
5039
+ }
5040
+
5009
5041
auto varLoc = vars[0]->getLoc();
5010
5042
5011
5043
Optional<InFlightDiagnostic> diag;
@@ -5235,6 +5267,7 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
5235
5267
}
5236
5268
5237
5269
} else {
5270
+ SmallPtrSet<VarDecl *, 4> backingStorageVars;
5238
5271
for (auto member : decl->getMembers()) {
5239
5272
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
5240
5273
// Initializers that were synthesized to fulfill derived conformances
@@ -5259,16 +5292,22 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
5259
5292
if (auto var = dyn_cast<VarDecl>(member)) {
5260
5293
// If this variable has a property delegate, go validate it to ensure
5261
5294
// that we create the backing storage property.
5262
- if (var->getAttachedPropertyDelegate ()) {
5295
+ if (auto backingVar = var->getPropertyDelegateBackingProperty ()) {
5263
5296
validateDecl(var);
5264
5297
maybeAddAccessorsToStorage(var);
5298
+
5299
+ backingStorageVars.insert(backingVar);
5265
5300
}
5266
5301
5302
+ // Ignore the backing storage for properties with attached delegates.
5303
+ if (backingStorageVars.count(var) > 0)
5304
+ continue;
5305
+
5267
5306
if (isMemberwiseInitialized(var)) {
5268
5307
// Initialized 'let' properties have storage, but don't get an argument
5269
5308
// to the memberwise initializer since they already have an initial
5270
5309
// value that cannot be overridden.
5271
- if (var->isLet() && var->getParentInitializer ()) {
5310
+ if (var->isLet() && var->isParentInitialized ()) {
5272
5311
5273
5312
// We cannot handle properties like:
5274
5313
// let (a,b) = (1,2)
@@ -5295,7 +5334,7 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
5295
5334
if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
5296
5335
if (pbd->hasStorage() && !pbd->isStatic()) {
5297
5336
for (auto entry : pbd->getPatternList()) {
5298
- if (entry.getInit ()) continue;
5337
+ if (entry.isInitialized ()) continue;
5299
5338
5300
5339
// If one of the bound variables is @NSManaged, go ahead no matter
5301
5340
// what.
0 commit comments