Skip to content

Commit a10cc92

Browse files
committed
Sema: Try to bind extensions without expanding macros
Macro expansion can call typeCheckExpr(), which performs qualified lookups. So if we expand macros while binding extensions, these qualified lookups can fail because they cannot find members of extensions that have not been bound yet. To fix this, try binding extensions without performing macro expansion first. If any extensions remain at the end, we fall back to the old behavior, and try to bind them again, this time performing macro expansion. Fixes rdar://149798059.
1 parent 0466387 commit a10cc92

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

lib/Sema/TypeChecker.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,14 @@ ModuleDecl *TypeChecker::getStdlibModule(const DeclContext *dc) {
191191
}
192192

193193
void swift::bindExtensions(ModuleDecl &mod) {
194+
bool excludeMacroExpansions = true;
195+
194196
// Utility function to try and resolve the extended type without diagnosing.
195197
// If we succeed, we go ahead and bind the extension. Otherwise, return false.
196198
auto tryBindExtension = [&](ExtensionDecl *ext) -> bool {
197199
assert(!ext->canNeverBeBound() &&
198200
"Only extensions that can ever be bound get here.");
199-
if (auto nominal = ext->computeExtendedNominal()) {
201+
if (auto nominal = ext->computeExtendedNominal(excludeMacroExpansions)) {
200202
nominal->addExtension(ext);
201203
return true;
202204
}
@@ -228,20 +230,28 @@ void swift::bindExtensions(ModuleDecl &mod) {
228230
visitTopLevelDecl(D);
229231
}
230232

231-
// Phase 2 - repeatedly go through the worklist and attempt to bind each
232-
// extension there, removing it from the worklist if we succeed.
233-
bool changed;
234-
do {
235-
changed = false;
236-
237-
auto last = std::remove_if(worklist.begin(), worklist.end(),
238-
tryBindExtension);
239-
if (last != worklist.end()) {
240-
worklist.erase(last, worklist.end());
241-
changed = true;
242-
}
243-
} while(changed);
233+
auto tryBindExtensions = [&]() {
234+
// Phase 2 - repeatedly go through the worklist and attempt to bind each
235+
// extension there, removing it from the worklist if we succeed.
236+
bool changed;
237+
do {
238+
changed = false;
239+
240+
auto last = std::remove_if(worklist.begin(), worklist.end(),
241+
tryBindExtension);
242+
if (last != worklist.end()) {
243+
worklist.erase(last, worklist.end());
244+
changed = true;
245+
}
246+
} while(changed);
247+
};
248+
249+
tryBindExtensions();
244250

251+
// If that fails, try again, but this time expand macros.
252+
excludeMacroExpansions = false;
253+
tryBindExtensions();
254+
245255
// Any remaining extensions are invalid. They will be diagnosed later by
246256
// typeCheckDecl().
247257
}

0 commit comments

Comments
 (0)