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