diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 95590524189fa..e12d409c2f754 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1523,6 +1523,9 @@ static VarDecl *synthesizePropertyWrapperStorageWrapperProperty( Identifier name = ctx.getIdentifier(nameBuf); // Determine the type of the property. + if (!wrapperVar->hasInterfaceType()) { + static_cast(*ctx.getLazyResolver()).validateDecl(wrapperVar); + } Type propertyType = wrapperType->getTypeOfMember( var->getModuleContext(), wrapperVar, wrapperVar->getValueInterfaceType()); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index aa4147921a8f9..140c32405fe21 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -5506,6 +5506,25 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target, if (!evaluateTargetConformanceTo(decodableProto)) (void)evaluateTargetConformanceTo(encodableProto); } + + if ((baseName.getIdentifier().str().startswith("$") || + baseName.getIdentifier().str().startswith("_")) && + baseName.getIdentifier().str().size() > 1) { + // $- and _-prefixed variables can be generated by properties that have + // attached property wrappers. + auto originalPropertyName = + Context.getIdentifier(baseName.getIdentifier().str().substr(1)); + for (auto member : target->lookupDirect(originalPropertyName)) { + if (auto var = dyn_cast(member)) { + if (var->hasAttachedPropertyWrapper()) { + auto sourceFile = var->getDeclContext()->getParentSourceFile(); + if (sourceFile && sourceFile->Kind != SourceFileKind::Interface) + (void)var->getPropertyWrapperBackingPropertyInfo(); + } + } + } + } + } else { auto argumentNames = member.getArgumentNames(); if (member.isCompoundName() && argumentNames.size() != 1) diff --git a/test/multifile/Inputs/rdar51725203.swift b/test/multifile/Inputs/rdar51725203.swift new file mode 100644 index 0000000000000..639bb23c37978 --- /dev/null +++ b/test/multifile/Inputs/rdar51725203.swift @@ -0,0 +1,23 @@ +@propertyWrapper +struct Wrapper { + var wrappedValue: Value + + var projectedValue: Wrapper { + get { self } + set { self = newValue } + } + + init(initialValue: Value) { + wrappedValue = initialValue + } +} + +struct StructModel { + @Wrapper var foo: Int + @Wrapper var bar: Int // expected-note{{'_bar' declared here}} +} + +class ClassModel { + @Wrapper var foo = 17 + @Wrapper var bar = 17 // expected-note{{'_bar' declared here}} +} diff --git a/test/multifile/property-wrappers-rdar51725203.swift b/test/multifile/property-wrappers-rdar51725203.swift new file mode 100644 index 0000000000000..4d6ed13b29f8d --- /dev/null +++ b/test/multifile/property-wrappers-rdar51725203.swift @@ -0,0 +1,9 @@ +// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/rdar51725203.swift + +func test(sm: StructModel, cm: ClassModel) { + _ = sm.$foo + _ = cm.$foo + + _ = sm._bar // expected-error{{'_bar' is inaccessible due to 'private' protection level}} + _ = cm._bar // expected-error{{'_bar' is inaccessible due to 'private' protection level}} +}