@@ -1362,7 +1362,9 @@ bool swift::accessorMacroOnlyIntroducesObservers(
1362
1362
for (auto name : attr->getNames ()) {
1363
1363
if (name.getKind () == MacroIntroducedDeclNameKind::Named &&
1364
1364
(name.getName ().getBaseName ().userFacingName () == " willSet" ||
1365
- name.getName ().getBaseName ().userFacingName () == " didSet" )) {
1365
+ name.getName ().getBaseName ().userFacingName () == " didSet" ||
1366
+ name.getName ().getBaseName ().getKind () ==
1367
+ DeclBaseName::Kind::Constructor)) {
1366
1368
foundObserver = true ;
1367
1369
} else {
1368
1370
// Introduces something other than an observer.
@@ -1413,24 +1415,28 @@ llvm::Optional<unsigned> swift::expandAccessors(AbstractStorageDecl *storage,
1413
1415
// Trigger parsing of the sequence of accessor declarations. This has the
1414
1416
// side effect of registering those accessor declarations with the storage
1415
1417
// declaration, so there is nothing further to do.
1416
- bool foundNonObservingAccessor = false ;
1417
- bool foundNonObservingAccessorInMacro = false ;
1418
- bool foundInitAccessor = false ;
1418
+ AccessorDecl * foundNonObservingAccessor = nullptr ;
1419
+ AccessorDecl * foundNonObservingAccessorInMacro = nullptr ;
1420
+ AccessorDecl * foundInitAccessor = nullptr ;
1419
1421
for (auto accessor : storage->getAllAccessors ()) {
1420
- if (accessor->isInitAccessor ())
1421
- foundInitAccessor = true ;
1422
+ if (accessor->isInitAccessor ()) {
1423
+ if (!foundInitAccessor)
1424
+ foundInitAccessor = accessor;
1425
+ continue ;
1426
+ }
1422
1427
1423
1428
if (!accessor->isObservingAccessor ()) {
1424
- foundNonObservingAccessor = true ;
1429
+ if (!foundNonObservingAccessor)
1430
+ foundNonObservingAccessor = accessor;
1425
1431
1426
- if (accessor->isInMacroExpansionInContext ())
1427
- foundNonObservingAccessorInMacro = true ;
1432
+ if (!foundNonObservingAccessorInMacro &&
1433
+ accessor->isInMacroExpansionInContext ())
1434
+ foundNonObservingAccessorInMacro = accessor;
1428
1435
}
1429
1436
}
1430
1437
1431
1438
auto roleAttr = macro->getMacroRoleAttr (MacroRole::Accessor);
1432
- bool expectedNonObservingAccessor =
1433
- !accessorMacroOnlyIntroducesObservers (macro, roleAttr);
1439
+ bool expectObservers = accessorMacroOnlyIntroducesObservers (macro, roleAttr);
1434
1440
if (foundNonObservingAccessorInMacro) {
1435
1441
// If any non-observing accessor was added, mark the initializer as
1436
1442
// subsumed unless it has init accessor, because the initializer in
@@ -1451,11 +1457,24 @@ llvm::Optional<unsigned> swift::expandAccessors(AbstractStorageDecl *storage,
1451
1457
storage->removeAccessor (accessor);
1452
1458
}
1453
1459
1454
- // Make sure we got non-observing accessors exactly where we expected to.
1455
- if (foundNonObservingAccessor != expectedNonObservingAccessor) {
1460
+ // If the macro told us to expect only observing accessors, but the macro
1461
+ // produced a non-observing accessor, it could have converted a stored
1462
+ // property into a computed one without telling us pre-expansion. Produce
1463
+ // an error to prevent this.
1464
+ if (expectObservers && foundNonObservingAccessorInMacro) {
1465
+ storage->diagnose (
1466
+ diag::macro_nonobserver_unexpected_in_expansion, macro->getName (),
1467
+ foundNonObservingAccessorInMacro->getDescriptiveKind ());
1468
+ }
1469
+
1470
+ // We expected to get a non-observing accessor, but there isn't one (from
1471
+ // the macro or elsewhere), meaning that we counted on this macro to make
1472
+ // this stored property into a a computed property... but it didn't.
1473
+ // Produce an error.
1474
+ if (!expectObservers && !foundNonObservingAccessor) {
1456
1475
storage->diagnose (
1457
- diag::macro_accessor_missing_from_expansion, macro-> getName () ,
1458
- !expectedNonObservingAccessor );
1476
+ diag::macro_nonobserving_accessor_missing_from_expansion ,
1477
+ macro-> getName () );
1459
1478
}
1460
1479
1461
1480
// 'init' accessors must be documented in the macro role attribute.
0 commit comments