@@ -1358,7 +1358,9 @@ bool swift::accessorMacroOnlyIntroducesObservers(
13581358 for (auto name : attr->getNames ()) {
13591359 if (name.getKind () == MacroIntroducedDeclNameKind::Named &&
13601360 (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)) {
13621364 foundObserver = true ;
13631365 } else {
13641366 // Introduces something other than an observer.
@@ -1409,24 +1411,28 @@ llvm::Optional<unsigned> swift::expandAccessors(AbstractStorageDecl *storage,
14091411 // Trigger parsing of the sequence of accessor declarations. This has the
14101412 // side effect of registering those accessor declarations with the storage
14111413 // 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 ;
14151417 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+ }
14181423
14191424 if (!accessor->isObservingAccessor ()) {
1420- foundNonObservingAccessor = true ;
1425+ if (!foundNonObservingAccessor)
1426+ foundNonObservingAccessor = accessor;
14211427
1422- if (accessor->isInMacroExpansionInContext ())
1423- foundNonObservingAccessorInMacro = true ;
1428+ if (!foundNonObservingAccessorInMacro &&
1429+ accessor->isInMacroExpansionInContext ())
1430+ foundNonObservingAccessorInMacro = accessor;
14241431 }
14251432 }
14261433
14271434 auto roleAttr = macro->getMacroRoleAttr (MacroRole::Accessor);
1428- bool expectedNonObservingAccessor =
1429- !accessorMacroOnlyIntroducesObservers (macro, roleAttr);
1435+ bool expectObservers = accessorMacroOnlyIntroducesObservers (macro, roleAttr);
14301436 if (foundNonObservingAccessorInMacro) {
14311437 // If any non-observing accessor was added, mark the initializer as
14321438 // subsumed unless it has init accessor, because the initializer in
@@ -1447,11 +1453,24 @@ llvm::Optional<unsigned> swift::expandAccessors(AbstractStorageDecl *storage,
14471453 storage->removeAccessor (accessor);
14481454 }
14491455
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) {
14521471 storage->diagnose (
1453- diag::macro_accessor_missing_from_expansion, macro-> getName () ,
1454- !expectedNonObservingAccessor );
1472+ diag::macro_nonobserving_accessor_missing_from_expansion ,
1473+ macro-> getName () );
14551474 }
14561475
14571476 // 'init' accessors must be documented in the macro role attribute.
0 commit comments