Skip to content

Commit 72f8d70

Browse files
authored
Merge pull request swiftlang#27645 from DougGregor/property-wrappers-lookup-source-compat
[Property wrappers] Fix source compatibility issue with attribute lookup
2 parents e7ab752 + 190d965 commit 72f8d70

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ ERROR(circular_protocol_def,none,
163163
NOTE(kind_declname_declared_here,none,
164164
"%0 %1 declared here", (DescriptiveDeclKind, DeclName))
165165

166+
WARNING(warn_property_wrapper_module_scope,none,
167+
"ignoring associated type %0 in favor of module-scoped property "
168+
"wrapper %0; please qualify the reference with %1",
169+
(DeclName, Identifier))
170+
166171
#ifndef DIAG_NO_UNDEF
167172
# if defined(DIAG)
168173
# undef DIAG

lib/AST/NameLookup.cpp

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,13 @@ void namelookup::recordLookupOfTopLevelName(DeclContext *topLevelContext,
648648
nameTracker->addTopLevelName(name.getBaseName(), isCascading);
649649
}
650650

651+
namespace {
652+
/// Whether we're looking up outer results or not.
653+
enum class LookupOuterResults {
654+
Excluded,
655+
Included
656+
};
657+
}
651658

652659
/// Retrieve the set of type declarations that are directly referenced from
653660
/// the given parsed type representation.
@@ -1878,11 +1885,15 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
18781885
/// Perform unqualified name lookup for types at the given location.
18791886
static DirectlyReferencedTypeDecls
18801887
directReferencesForUnqualifiedTypeLookup(DeclName name,
1881-
SourceLoc loc, DeclContext *dc) {
1888+
SourceLoc loc, DeclContext *dc,
1889+
LookupOuterResults lookupOuter) {
18821890
DirectlyReferencedTypeDecls results;
18831891
UnqualifiedLookup::Options options =
18841892
UnqualifiedLookup::Flags::TypeLookup |
18851893
UnqualifiedLookup::Flags::AllowProtocolMembers;
1894+
if (lookupOuter == LookupOuterResults::Included)
1895+
options |= UnqualifiedLookup::Flags::IncludeOuterResults;
1896+
18861897
UnqualifiedLookup lookup(name, dc, loc, options);
18871898
for (const auto &result : lookup.Results) {
18881899
if (auto typeDecl = dyn_cast<TypeDecl>(result.getValueDecl()))
@@ -1957,7 +1968,8 @@ directReferencesForIdentTypeRepr(Evaluator &evaluator,
19571968
current =
19581969
directReferencesForUnqualifiedTypeLookup(component->getIdentifier(),
19591970
component->getIdLoc(),
1960-
dc);
1971+
dc,
1972+
LookupOuterResults::Excluded);
19611973

19621974
// If we didn't find anything, fail now.
19631975
if (current.empty())
@@ -2195,6 +2207,19 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
21952207
return nominalTypes.empty() ? nullptr : nominalTypes[0];
21962208
}
21972209

2210+
/// Whether there are only associated types in the set of declarations.
2211+
static bool declsAreAssociatedTypes(ArrayRef<TypeDecl *> decls) {
2212+
if (decls.empty())
2213+
return false;
2214+
2215+
for (auto decl : decls) {
2216+
if (!isa<AssociatedTypeDecl>(decl))
2217+
return false;
2218+
}
2219+
2220+
return true;
2221+
}
2222+
21982223
llvm::Expected<NominalTypeDecl *>
21992224
CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
22002225
CustomAttr *attr, DeclContext *dc) const {
@@ -2217,6 +2242,48 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
22172242
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front()))
22182243
return nominals.front();
22192244

2245+
// If we found declarations that are associated types, look outside of
2246+
// the current context to see if we can recover.
2247+
if (declsAreAssociatedTypes(decls)) {
2248+
if (auto typeRepr = typeLoc.getTypeRepr()) {
2249+
if (auto identTypeRepr = dyn_cast<SimpleIdentTypeRepr>(typeRepr)) {
2250+
auto assocType = cast<AssociatedTypeDecl>(decls.front());
2251+
2252+
modulesFound.clear();
2253+
anyObject = false;
2254+
decls = directReferencesForUnqualifiedTypeLookup(
2255+
identTypeRepr->getIdentifier(), identTypeRepr->getIdLoc(), dc,
2256+
LookupOuterResults::Included);
2257+
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls,
2258+
modulesFound, anyObject);
2259+
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front())) {
2260+
auto nominal = nominals.front();
2261+
if (nominal->getDeclContext()->isModuleScopeContext()) {
2262+
// Complain, producing module qualification in a Fix-It.
2263+
auto moduleName = nominal->getParentModule()->getName();
2264+
ctx.Diags.diagnose(typeRepr->getLoc(),
2265+
diag::warn_property_wrapper_module_scope,
2266+
identTypeRepr->getIdentifier(),
2267+
moduleName)
2268+
.fixItInsert(typeRepr->getLoc(),
2269+
moduleName.str().str() + ".");
2270+
ctx.Diags.diagnose(assocType, diag::kind_declname_declared_here,
2271+
assocType->getDescriptiveKind(),
2272+
assocType->getFullName());
2273+
2274+
ComponentIdentTypeRepr *components[2] = {
2275+
new (ctx) SimpleIdentTypeRepr(typeRepr->getLoc(), moduleName),
2276+
identTypeRepr
2277+
};
2278+
2279+
typeLoc = TypeLoc(IdentTypeRepr::create(ctx, components));
2280+
return nominal;
2281+
}
2282+
}
2283+
}
2284+
}
2285+
}
2286+
22202287
return nullptr;
22212288
}
22222289

test/decl/var/property_wrappers.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,3 +1779,13 @@ struct SR_11477_W3 { // Okay
17791779
get { return 0 }
17801780
}
17811781
}
1782+
1783+
// rdar://problem/56213175 - backward compatibility issue with Swift 5.1,
1784+
// which unconditionally skipped protocol members.
1785+
protocol ProtocolWithWrapper {
1786+
associatedtype Wrapper = Float // expected-note{{associated type 'Wrapper' declared here}}
1787+
}
1788+
1789+
struct UsesProtocolWithWrapper: ProtocolWithWrapper {
1790+
@Wrapper var foo: Int // expected-warning{{ignoring associated type 'Wrapper' in favor of module-scoped property wrapper 'Wrapper'; please qualify the reference with 'property_wrappers'}}{{4-4=property_wrappers.}}
1791+
}

0 commit comments

Comments
 (0)